0

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

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

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

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

我究竟做错了什么?

4

2 回答 2

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

这个比较靠谱。

于 2012-07-09T18:41:10.213 回答
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 文件 globbing 中的+(...)构造仅在extglob设置时可用。

不是使用循环遍历目录树 and cd,而是find用于获取所有相关文件的列表,然后循环遍历该文件名列表,其形式为:./pippoN/pippoN.txt. 重命名使用 bash参数替换来获取修改后的文件名。另请参见文件名扩展

请注意,文件或目录名称中的空格会破坏这种方法,首先使用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循环迭代器中的问题。现在路径中的空格将被正确处理,因此 eg./pippo 9/pippo9.txt也将被重命名为:./pippo 9/pippo.txt

于 2012-07-09T19:10:53.447 回答