我遇到过这样的情况,有一些输入文件:
M2U0001.MPG
M2U0180.MPG
我想要对目录中每个名称相似的文件运行一个命令(在 Bash shell 中)。我希望将当前文件名作为输入提供给此命令,并将文件名的修改版本作为输出文件。以下是示例:
ffmpeg -i M2U0001.MPG M2U0001_fixed.MPG
我曾想过使用 xargs 和 sed,但我只能做到以下几点:
ls -1 *.MPG | xargs -I{} ffmpeg -i {} `echo {} | sed -r 's/[0-9]{2,}/&_fixed/'`
但这会导致原始文件名在两个位置都输出。我的做法是不是完全错误了?
我发现如果我将文件名直接回显到嵌入的块,就像这样它就可以起作用:
echo M2U0001.MPG | sed -r 's/[0-9]{2,}/&_fixed/'
答案1
答案2
for i in $(ls)
不应该使用 - ls(1) 输出不应该用于通过脚本等进行解析,因为单词拆分,这是我在工作中在 Bash 脚本中看到的常见错误。
在这种情况下,参数扩展可以正常工作,并且不易受到单词拆分错误的影响。
for i in *.MPG; do ffmpeg -i "$i" "${i%%.*}"_fixed.MPG ; done
答案3
find . -iname "*.mpg" -exec sh -c "ffmpeg -i {} `echo {} | sed -e 's/\./_fixed\./'`" \;
答案4
以下是一个具体的变化:
ls -1 src/*.c | xargs -i sh -c "echo;gcc -fpreprocessed -dD -E {} 2>&1 | grep -wi -e one -e two -e three -n | sed 's:^:{}\::'" | cat -s
C 源文件列表,
ls -1 src/*.c
通过管道传输到 xargs,后者在子 shell 中执行预处理器,
gcc -fpreprocessed -dD -E {} 2>&1
随后将其输入到所需的 grep 命令中
grep -wi -e one -e two -e three -n
然后将其通过管道传输到 sed 中,在每行前面加上当前文件名作为前缀:
sed 's:^:{}\::'
最后,使用 cat 将所有重复的空白行折叠为单行:
cat -s
这在 Red Hat Linux 6 系统上运行,但我认为它对其他 *nix 系统来说足够通用。