我想了解更多,所以我尝试编写脚本,而不仅仅是使用终端。我知道rename
我可以使用重命名图像文件,rename 's/ /_/g' *.jpg
但是当我在 shell 脚本中编写它以指向目录时:
DIRECTORY="/foo/bar"
for imgfile in $(find $DIRECTORY -type f -name \*.jpg); do
echo 'replacing whitespace in' $(basename $imgfile)
rename -f 's/ /_/g' *.jpg
done
它不起作用,终端将获取一个文件(例如:)1234 abcd.jpg
并回显abcd.jpg
。那么我哪里错了?
答案1
文件名中的空格是有害的。
我发现该脚本存在三个问题:
当执行
for...
循环时,如果找到带有空格的文件,则会得到两个不同的值。即,如果您有文件"file1 1.jpg"
并且"file2 2.jpg"
您执行以下操作:for i in $(find . -type f -name \*.jpg); do echo $i done
你将拥有
./file1 1.jpg ./file2 2.jpg
因为 shell 会在空格处中断参数。该
$(find ...)
命令的输出将是./file1 1.jpg ./file2 2.jpg
这是为命令
for
指定的四个字$i
--- 默认情况下,shell 在扩展时以相同的方式处理空格和换行符。你可以规避这个问题改变 IFS 字符。
你的第一行可能看起来像这样:
IFS=$'\n' find $DIRECTORY -type f -name \*.jpg | while read -r imgfile; do
你正在为 for 循环提供单个文件名,因此你应该说:
rename -f 's/ /_/g' "$imgfile"
否则
*.jpg
将在当前目录中扩展,而不是在$DIRECTORY
(请注意引号 --- 因为$imgfile
其中会有空格)。即使如此,如果
$DIRECTORY
某个路径部分中有空格,重命名也会失败(中间目录不存在)。建议(保持简单):
DIRECTORY="/foo/bar" cd $DIRECTORY rename -f 's/ /_/g' *.jpg
没有达到你想要的效果?
添加:我的脚本(很久以前创建,当时 Unix 中还没有rename
),是这样的 --- 它将删除当前目录中名称中包含空格和制表符的所有文件:
#
ls -1 | grep -E " |\t" | while read i; do
a=`echo $i | tr " \t" "__"`
mv -v "$i" $a
done
已添加++:此链接我发现研究这个答案非常好。
答案2
解析结果的最佳方法find
是使用 null 终止输出-print0
#!/bin/bash
while IFS= read -d '' -r; do
rename -f "s/ /_/g" "$REPLY"
if [[ ! -f $REPLY ]]; then
echo "Renaming file: $(basename "$REPLY")"
fi
done < <(find -type f -name '*.jpg' -print0)
(无需循环即可进行管理)。
$ find -type f -name '*.jpg' \
-exec bash -c 'rename -f "s/ /_/g" "$1"; \
[[ -f $1 ]] || echo "Renaming file: $(basename "$1")"' _ '{}' \;