使用示例(人为!):将 .mp3 文件重命名为 .txt。
我希望能够做类似的事情
find -name '*.mp3' -print0 | xargs -0 -I'file' mv file ${file%.mp3}.txt
这不起作用,所以我使用了 pipefind
的输出 through sed -e 's/.mp3//g'
,这可以解决问题。
不过似乎有点骇人听闻;有没有办法使用通常的 bash${x%y}
语法?
不,xargs -0 -I'file' mv file ${file%.mp3}.txt
不会起作用,因为该file
变量将由 xargs 程序而不是 shell 扩展。实际上将其称为变量并不完全正确,在xargs的手册中称为“replace-str”。
更新:要只使用 xargs 和 bash (而不是 sed 或类似的),你当然可以让 xargs 启动一个 bash 进程,然后可以做任何你想要的替换:
find -name '*.mp3' -print0 | xargs -0 bash -c \
'while [ -n "$1" ]; do mv "$1" "${1%.mp3}.txt" ; shift; done;' "bash"
只是添加另一个建议,即使它不使用 shell 的替换机制,而是使用 sed 的。
find -name '*.mp3' -print |
sed -e 's/\.mp3$//' -e "s/.*/mv '&\.mp3' '&\.txt'/" |
sh
换句话说,mv
为每个文件名创建一个命令行,并将结果传递给sh
.
如果任何文件的文件名中有撇号(单引号),这将失败。我主要发布这个来对抗“如果你只有 xargs,每个问题都会看起来像钉子”综合症。
并非所有 sed 都具有完全相同的语法。特别是,我不能 100% 确定您可以在一些笨拙的旧 SunOS 上使用多个 -e 参数(在类似的内容中查找与 XPG 兼容的 sed /usr/ucb/blah/barf/vomit/xpg4/bin/sed
)
如果您安装了 GNU Parallel:
find -name '*.mp3' -print0 | parallel -0 mv {} {.}.txt
如果您的文件名不包含 \n (换行符),这也可以:
find -name '*.mp3' | parallel mv {} {.}.txt
观看介绍视频以了解有关 GNU Parallel 的更多信息http://www.youtube.com/watch?v=OpaiGYxkSuQ
find . -type f -name '*.mp3' | while read -r F
do
mv "$F" "${F%.mp3}.txt"
done
重击 4+
shopt -s globstar
shopt -s nullglob
for file in **/*.mp3
do
mv "$file" "${file%.mp3}.txt"
done
perl rename.pl 's/\.mp3$/.txt/' *.mp3
# Or **/*.mp3 for zsh and bash with specific settings set, for a recursive
# rename.
http://people.sc.fsu.edu/~jburkardt/pl_src/rename/rename.html