how do I echo only white space and no newline

2019-07-10 00:32发布

问题:

I'm working on a simple batch script that loops over files in a directory and process them with ffmpeg. for readability purposes, I want to indent the ffmpeg output 4 spaces, but I cannot come up with a way that works.

@echo off

for %%a in (%~dp0rawVideo\*.MP4) do (

    if exist %~dp0rawAudio\%%~na.wav (
        echo Already Processed :
        echo     %%a
    ) else (
        echo Processing :
        echo     %%a
        echo|set /p leadingSpace="#   "   
        ffmpeg -c:v h264 -threads 24 -i %%a -map_channel 0.1.0 -map_channel -1 -y -v quiet -stats %~dp0rawAudio\%%~na.wav
    )

    echo(
)
pause

If I just do this i get nothing, because I've read windows strips leading white spaces.

echo|set /p leadingSpace="    " 

I tried what I think is the backspace trick as well, but it didn't work. Is there no way of doing this?

回答1:

1st solution

Here's a way to run your command and prefix each line outputted by a prefix.

Simple example without arguments:

@echo off
for /F "delims=" %%a in ('ffmpeg.exe 2^>^&1') do echo #    %%a

issues:

#    ffmpeg version N-80980-g7af44ce Copyright (c) 2000-2016 the FFmpeg developers
#      built with gcc 5.4.0 (GCC)
#      configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-dxva2 --enable-li
bmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-libebur128 --enable-fontconfig --enabl
e-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable
-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug -
-enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enab
le-libopus --enable-librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-li
bspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-l
ibvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --en
able-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib
#      libavutil      55. 28.100 / 55. 28.100
#      libavcodec     57. 50.100 / 57. 50.100
#      libavformat    57. 41.100 / 57. 41.100
#      libavdevice    57.  0.102 / 57.  0.102
#      libavfilter     6. 47.100 /  6. 47.100
#      libswscale      4.  1.100 /  4.  1.100
#      libswresample   2.  1.100 /  2.  1.100
#      libpostproc    54.  0.100 / 54.  0.100
#    Hyper fast Audio and Video encoder
#    usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
#    Use -h to get full help or, even better, run 'man ffmpeg'

it redirects standard error to standard output (so error messages are also prefixed) and uses empty delimiter, so %%a is the full line.

Since you are called each time a line is issued, it is easy to echo it the way you want.

Of course it also works if the command issues just one line.

2nd solution

Since you only have one line, an alternative would be to use a temporary file to get the output of ffmpeg, then assign a variable interactively with this file redirected as input. Then echo it as you want:

ffmpeg -c:v h264 -threads 24 -i %%a -map_channel 0.1.0 -map_channel -1 -y -v quiet -stats %~dp0rawAudio\%%~na.wav> %TEMP%\tmpf
set /P ffmpegout=<%TEMP%\tmpf
echo     %ffmpegout%


回答2:

This is a pure Batch file method to create a file with any number of spaces and no line feed at end, so it may be displayed via type spaces.txt before a set /P command in order to show leading spaces:

@echo off
setlocal

call :createFourSpaces
type fourSpaces.txt
set /P "=After the spaces" < NUL
echo/
exit /B

:createFourSpaces
for %%X in (^"^
% Do NOT remove this line %
^") do set /P "=X%%~X    " > fourSpaces.tmp <NUL
findstr /V "X" fourSpaces.tmp > fourSpaces.txt
del fourSpaces.tmp
exit /B


回答3:

You could pipe the output into any utility that provides search/replace capability. There isn't a native Windows batch command available, but you could use something like JREPL.BAT - a regular expression text processing utility. JREPL.BAT is pure script (hybrid batch/JScript) that runs natively on any Winidows machine form XP onward - no 3rd party exe file is required. Full documentation is available from the command line via jrepl /?, or jrepl /?? for paged help.

@echo off
for %%a in (%~dp0rawVideo\*.MP4) do (
    if exist %~dp0rawAudio\%%~na.wav (
        echo Already Processed :
        echo     %%a
    ) else (
        echo Processing :
        echo     %%a
        ffmpeg -c:v h264 -threads 24 -i %%a -map_channel 0.1.0 -map_channel -1 -y -v quiet -stats %~dp0rawAudio\%%~na.wav | jrepl "^" "    "
    )
    echo(
)
pause

There is a significant delay each time JREPL is called because the CSCRIPT engine must be instantiated, and the JScript must be compiled. Once started, the utility is very fast. But in this case, the fractional second delay for each iteration could be irritating.

Performance can be dramatically improved if you pipe the entire FOR loop output through a single instance of JREPL. The only trick is to structure the search to only match lines that need to be prefixed.

Here I assume that ffmpeg always puts a non-space character in the first position of each line of output, and the ffmpeg output never contains "Process"

@echo off
(
  for %%a in (%~dp0rawVideo\*.MP4) do @(
    if exist %~dp0rawAudio\%%~na.wav (
      echo Already Processed :
      echo     %%a
    ) else (
      echo Processing :
      echo     %%a
      ffmpeg -c:v h264 -threads 24 -i %%a -map_channel 0.1.0 -map_channel -1 -y -v quiet -stats %~dp0rawAudio\%%~na.wav
    )
    echo(
  )
) | jrepl "^(?=[^ ])(?!.*Process)" "    "
pause