我有一些工作代码,非常简单 - 它复制每个 *.jpg 文件,将其重命名为 *1.jpg,不用担心。
for i in *.jpg; do cp $i ${i%%.jpg}1.jpg; done
我该如何运行它,以便它适用于目录中的每个文件,该目录的子目录中的每个文件
示例目录结构:
test/test1/test2/somefile.jpg
test/anotherfile.jpg
test/test1/file.jpg
etc
以递归方式对目录结构执行任何操作的命令是find
:
find . -name "*.jpg" -exec bash -c 'file="{}"; cp "$file" "${file%%.jpg}1.jpg"' \;
使用-exec
代替for i in $(find ...)
将处理包含空格的文件名。当然,还有一个引用陷阱;如果文件名包含 a "
,file="{}"
则将扩展为file="name containing "quote characters""
,这显然已损坏(file
将变为name containing quote
并尝试执行characters
命令)。
如果你有这样的文件名,或者你可能有,那么使用 打印出用空字符(文件名中不允许的)分隔的每个文件名-print0
,并使用while read -d $'\0' i
循环以空分隔的结果:
find . -name "*.jpg" -print0 | \
(while read -d $'\0' i; do cp "$i" "${i%%.jpg}1.jpg"; done)
与任何像这样的复杂命令一样,最好在不执行任何操作的情况下对其进行测试,以确保它在运行之前扩展为合理的东西。最好的方法是在实际命令前面加上echo
,因此您将看到它将运行的命令,而不是运行它:
find . -name "*.jpg" -print0 | \
(while read -d $'\0' i; do echo cp "$i" "${i%%.jpg}1.jpg"; done)
一旦你注意到它并且结果看起来不错,删除echo
并再次运行它以真正运行它。
如果你有 Bash 4,你可以globstar
用来启用递归文件名扩展(即匹配子目录中的文件)
shopt -s globstar
for i in **/*.jpg; do cp "$i" "${i%%.jpg}1.jpg"; done
p / s:我在参数周围添加了引号cp
,以防文件名中有空格或诸如此类。