Bash Shell Loop在文件夹集

时间:2012-07-09 18:07:33

标签: unix

我有一个文件夹列表。每个文件夹名称例如:

  • 包含pippo1.txt文件的pippo1,
  • 包含文件pippo2.txt,
  • 的pippo2
  • 包含文件pippo3.txt等的pippo3。

我想进入第一个文件夹,从文件名pippo1.txt中删除数字,然后退出,进入名为pippo2的第二个文件夹,其中包含文件pippo2.txt,从文件名中删除2等等。尝试了以下代码,但它不起作用!代码是:

for i in *
do
    cd $i
    ls *.txt | sed -e "s/[0-9]//g"
    cd ..
done

我做错了什么?

2 个答案:

答案 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