命令行历遍文件主要的目的还是处理一些问题清晰,只不过所使用的工具不支持glob选择方法, 又不是很想去用代码套一个壳子的情况下,迅速解决问题。例如:使用ffmpeg批量转换目录下 wav音频格式为flac音频格式;批量重命名名称构成简单的文件……

Linux 平台

for var in *.ext; do echo $var; done

Linux Shell的for循环应该说是非常的intuitive,如果简单的glob没办法简易地选取适当 的文件,那么总是可以通过grep等工具筛出需要的文件列表:

for var in $(ls *.flac | grep -v "high-res"); do echo $var; done

Windows 平台

cmd.exe

for /r %i in (*.ext) do echo %i

相对来说Windows当中的cmd命令行就稍显麻烦一点,首先需要启用/r开关。如果长时间不用, 很容易困惑于到底用/f,/d,/r还是/l开关。除此之外就是cmd的for命令具有非常厉害 的变量扩展。以具体实例转换wav音频格式为flac音频格式为例,你肯定不会愿意最终得到的文件名 长得像是something.wav.flac吧?

for /r %i in (*.wav) do ffmpeg -i "%i" "%~ni.flac"

通过在变量名前,变量提示符后添加~n使得变量名(也就是文件名)去除扩展名,而同样的功能 在Linux中,就稍显麻烦,考察以下实例:

$ echo "mp4.tar" | rev | cut -f 2- -d'.' | rev
mp4
$ echo "mp4.tar.xz" | rev | cut -f 2- -d'.' | rev
mp4.tar
$ 
$ fn="mp4.tar.xz"
$ echo "${fn%.*}"
mp4.tar

最后的一个实例使用的是Shell的参数扩展,详参手册

PowerShell

至于这个反人类的PowerShell,可以的话我是尽量希望避免的,但怎奈UNC目录名下只支持这个命令行 (比如挂载的SMB共享目录里),实在是没什么办法。仍然以音频格式转换为例:

Get-ChildItem . -Filter *.wav | ForEach-Object {
  ffmpeg -i $_.FullName  ".\video_new\$($_.Name).flac"
}

你说我们用命令行不就是为了节约时间的吗?为什么要打那么多字?