我有一个文件夹列表。每个文件夹名称例如:
我想进入第一个文件夹,从文件名pippo1.txt中删除数字,然后退出,进入名为pippo2的第二个文件夹,其中包含文件pippo2.txt,从文件名中删除2等等。尝试了以下代码,但它不起作用!代码是:
for i in *
do
cd $i
ls *.txt | sed -e "s/[0-9]//g"
cd ..
done
我做错了什么?
答案 0 :(得分:2)
切换目录时,调用子shell是最好也是最干净的。
重命名文件时,通常最好使用本地rename
命令,或获取一个。麻烦的是,有几个“标准”rename
命令,分布更广泛的命令远没有基于Perl的命令强大。这种方法避免了rename
,但并不完全可取:
for dir in *
do
(
cd "$dir"
for file in *[0-9].txt
do
mv "$file" $(echo "$file" | sed 's/[0-9]\.txt$/.txt/')
done
)
done
基于Perl的rename
将正则表达式作为第一个参数并将其应用于文件名:
for dir in *
do
(
cd "$dir"
rename 's/\d\.txt$/.txt/' *[0-9].txt
)
done
这更可靠。
答案 1 :(得分:2)
如果要求就是那么简单,那么你可以只用bash替换来做到这一点:
for file in `find . -name 'pippo*.txt'`; do
mv $file ${file/[0-9].txt/.txt}
done
然而,这将在文件名中的多个数字上失败,例如pippo999/pippo999.txt
。这可以通过设置extglob
选项来解决:
shopt -s extglob
for file in `find . -name 'pippo*.txt'`; do
mv $file ${file/+([0-9]).txt/.txt}
done
bash文件通配中的+(...)
构造仅在设置extglob
时可用。
不是使用循环和cd
遍历目录树,而是使用find
获取所有相关文件的列表,然后循环遍历文件名列表,这将是表单的形式:./pippoN/pippoN.txt
。重命名使用bash parameter replacement来获取修改后的文件名。另请参阅filename expansion。
请注意,文件或目录名称中的空格将破坏此方法,从使用find
开始:包含空格的路径将拆分为空格周围的多个标记每个标记都是列表迭代器中的单独结果。因此,如果您需要预测路径中的空格字符,那么这会变得有点复杂:
shopt -s extglob
IFS=$'\n'
for file in `find . -name 'pippo*.txt'`; do
mv "$file" "${file/+([0-9]).txt/.txt}"
done
这里我们引用了mv
命令的文件名,它将正确处理空格,我们更改了字段分隔符IFS
,以便bash不会将空格识别为单词边界。这将解决循环迭代器中find
的问题。现在路径中的空间将被正确处理,例如, ./pippo 9/pippo9.txt
也将重命名为:./pippo 9/pippo.txt
。