按特定顺序重命名一组文件而不会丢失它们(在Linux上)

时间:2015-06-24 23:41:10

标签: linux bash file-rename

我有一组文件(列表较大,4x43文件扩展名为I.sto,Q.sto,U.sto和V.sto):

probni45069Q.sto probni45080I.sto probni45080V.sto probni45083U.sto 
probni45069U.sto probni45080Q.sto probni45083I.sto probni45083V.sto
probni45069I.sto probni45069V.sto probni45080U.sto probni45083Q.sto

我的目标是按照从数字1开始的排序顺序重命名它们:

  1. probni45069I.sto probni1I.sto
  2. probni45080I.sto probni2I.sto
  3. probni45083I.sto probni3I.sto
  4. probni45069Q.sto probni1Q.sto
  5. probni45080Q.sto probni2Q.sto
  6. probni45083Q.sto probni3Q.sto
  7. probni45069U.sto probni1U.sto
  8. probni45080U.sto probni2U.sto
  9. probni45083U.sto probni3U.sto
  10. probni45069V.sto probni1V.sto
  11. probni45080V.sto probni2V.sto
  12. probni45083V.sto probni3V.sto
  13. 我已按照Renaming files in a folder to sequential numbers的说明和指南创建了以下bash脚本:

    model='probni'
    
    for sto in I Q U V;
    do
        i=1
        for j in $model*$sto.sto;
        do
            echo "$j" `printf $model%1d$sto.sto $i`
            mv "$j" `printf $model%1d$sto.sto $i` 2>/dev/null || true
            i=$((i + 1))
        done
    done
    

    此脚本仅在使用一次时效果很好。问题是当我在已经排序的文件集上多次使用它时,或者当我有一组已排序的文件以及其他未排序的文件(例如probni1I.sto + probni1346I.sto)时,我丢失了一定数量的文件。在我原来的4x43文件集上重复使用时,我最终以4x7文件集结束。

    我的问题是如何使这个脚本对于排序文件是幂等的,或者如何只是将新的未排序文件添加到排序列表而不丢失任何文件。

3 个答案:

答案 0 :(得分:2)

问题是文件名是按字典顺序排序的,这会导致数字出现问题,因为1 2 1346将排序为1 1346 2,因为字符1位于2之前。您需要更智能的排序,更直观地处理数字。

sort -g正是医生所要求的。通过sort -g1346过滤您的文件列表不会给您带来更多麻烦。

for j in $(ls $model*$sto.sto | sort -g); do
    ...
done

通常parsing the output of ls is a bad idea。如果你想做的事情非常正确,你需要重新构建一些事情。

for sto in I Q U V; do
    find -maxdepth 1 -name "$model*$sto.sto" -print0 |
        sort --files0-from - -z |
    {
        i=1
        while IFS= read -rd $'\0' old; do
            new=$model$i$sto.sto
            [[ $old == $new ]] && continue
            echo "$old" "$new"
            mv -- "$old" "$new" 2>/dev/null || true
            ((i++))
        done
    }
done

这是一项很多工作,但是这个版本处理奇怪的文件名要好得多。它在所有阶段都使用NUL分隔符,因此带有空格和换行符的文件名不会对作品产生影响。

我不希望你有这样奇怪的文件,但是嘿,比抱歉更安全。尝试做正确的事情总是好的。

答案 1 :(得分:0)

只要目标文件已存在,如何在循环中递增i?

while [ ! -f FILENAME ]
do
    INCREMENT
done

编辑:我错过了你的输入和输出文件看起来一样。这将要求你要么1)改变其中任何一个的命名方案,2)将它们放在不同的目录中,或者3)在你从1开始计算间隙时开始重命名

答案 2 :(得分:0)

通常解析ls的输出被认为是错误的。但是,如果文件夹仅包含显示模式后面的文件,则可以使用以下shell脚本:

ls | sort -k1.12 -k2.6n | awk '{
    n=substr($0,7,5);
    l=substr($0,12,1);
    c[l]++;
    system("mv "$0" probni"c[l]""l".sto")
}'

sort -k1.12 -k2.6n将按照末尾的字母和中间的数字对文件进行排序。这只适用于文件名长度相同且数字总是5个字符长,前缀总是probni(长6个字符)。

管道末尾的awk脚本使用substr()反汇编文件名,并按照所需模式重新组装。 system()用于发出mv命令。