我想替换文件名中的空格。我的测试目录中包含有空格的文件。
$ ls
'1 2 3.txt' '4 5.txt' '6 7 8 9.txt'
比如这段代码就很好用
$ printf "$(printf 'spaces in file name.txt' | sed 's/ /_/g')"
spaces_in_file_name.txt
我把下划线上的空格替换掉,然后命令替换的结果是双引号作为文本。在接下来的情况下,这种重要的替换结构是必不可少的。诸如以下命令 找到 和 xargs 有代入感 {}大括号)。因此接下来的命令可以替换文件中的空格。
$ find ./ -name "*.txt" -print0 | xargs --null -I '{}' mv '{}' "$( printf '{}' | sed 's/ /_/g' )"
mv: './6 7 8 9.txt' and './6 7 8 9.txt' are the same file
mv: './4 5.txt' and './4 5.txt' are the same file
mv: './1 2 3.txt' and './1 2 3.txt' are the same file
但我得到的是错误。为了更清楚地考虑到错误,我将用 mv 我只是用 回响(或 printf):
$ find ./ -name "*.txt" -print0 | xargs --null -I '{}' echo "$( printf '{}' | sed 's/ /_/g' )"
./6 7 8 9.txt
./4 5.txt
./1 2 3.txt
正如我们所看到的,下划线上的空格没有被替换。但是如果没有命令替换,替换的结果是正确的。
$ find ./ -name "*.txt" -print0 | xargs --null -I '{}' printf '{}\n' | sed 's/ /_/g'
./6_7_8_9.txt
./4_5.txt
./1_2_3.txt
所以命令替换的事实是 大括号 破坏了结果(因为第一条命令的结果是正确的),但如果不替换命令,结果是正确的。但是为什么呢?
你的命令替换运行 之前 find
而你正在执行
mv '{}' "{}"
你可以改变 find
命令,以匹配 .txt
文件中至少有一个空格字符,并使用 -exec
和一个小的bash脚本来重命名这些文件。
find . -type f -name "* *.txt" -exec bash -c '
for file; do
fname=${file##*/}
mv -i "$file" "${file%/*}/${fname// /_}"
done
' bash {} +
${file##*/}
删除父目录(最长的前缀模式) */
),并留下文件名(如 basename
命令)${file%/*}
删除文件名(最短后缀模式) /*
),并留下父目录(如 dirname
命令)${fname// /_}
用下划线代替所有空格这是很快速和简单的循环,只需替换为 absolute_path
与你的路径。
for f in absolute_path/*.txt; do mv "$f" "${f// /_}";done
的 ${f// /_}
部分利用bash的参数扩展机制,用提供的字符串替换参数中的模式。