Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 按顺序为不同文件夹中的文件编号,同时将名称保留在编号后_Bash_Rename_Find - Fatal编程技术网

Bash 按顺序为不同文件夹中的文件编号,同时将名称保留在编号后

Bash 按顺序为不同文件夹中的文件编号,同时将名称保留在编号后,bash,rename,find,Bash,Rename,Find,我在不同的文件夹中有很多ogg或wave文件,我想按顺序编号,同时保留前缀后面的所有内容。输入可能如下所示 Folder1/01 Insbruck.ogg 02 From Milan to Rome.ogg 03 From Rome to Naples.ogg Folder2/01 From Naples to Palermo.ogg 02 From Palermo to Syracrus.ogg 03 From Syracru

我在不同的文件夹中有很多ogg或wave文件,我想按顺序编号,同时保留前缀后面的所有内容。输入可能如下所示

Folder1/01 Insbruck.ogg
        02 From Milan to Rome.ogg
        03 From Rome to Naples.ogg


Folder2/01 From Naples to Palermo.ogg
        02 From Palermo to Syracrus.ogg
        03 From Syracrus to Tropea
输出应为:

Folder1/01 Insbruck.ogg
        02 From Milan to Rome.ogg
        03 From Rome to Naples.ogg

Folder2/04 From Naples to Palermo.ogg
        05 From Palermo to Syracrus.ogg
        06 From Syracrus to Tropea.ogg
可以使用我发现的这个BASH脚本对文件夹进行顺序编号:

但是这个脚本删除了我想保留的标题。

TL;博士 像这样,使用和perl
重命名

rename -n 's@/\d+@sprintf "/%0.2d", ++$::c@e' Folder*/*
如果输出看起来不错,请放下
-n
开关

使用
-n
,您只能看到真正要重命名的文件,因此只有
Folder2
中的3个文件


进一步 变量
$::c
(或
$main::c
是一个包变量)是一个小技巧,可以避免使用更复杂的表达式:

rename -n 's@/\d+@sprintf "/%0.2d", ++our $c@e' Folder*/*

感谢go | dfish&Grinnz在freenode上的支持

可以使用我在此处找到的BASH脚本对文件夹进行顺序编号:

但是这个脚本删除了我想保留的标题


虽然没有公认的答案那么可靠,但这是脚本的改进版本,只是以防万一,
rename
不可用

#/usr/bin/env bash
[n$1]||{
printf>&2'需要一个目录作为参数!\n'
出口1
}
n=1
目录=(“$@”)
而IFS=read-r文件;做
如果[[$files=~^(+.+)?\/([[:digit:][]+[^[:blank:][]+)(.+)$]);然后
printf-v int“%02d'”$((n++)“)
[[-e“${BASH_REMATCH[1]}/$int${BASH_REMATCH[3]}”]]&&{
printf“%s”已按顺序排列,正在跳过!\n'$files“
持续
} 
echo mv-v“$files”“${BASH_REMATCH[1]}/$int${BASH_REMATCH[3]}”
fi

完成此作业的bash脚本将是:

#!/bin/bash

argc=$#
width=${#argc}

n=0
for src; do
    base=$(basename "$src")
    dir=$(dirname "$src")
    if ! [[ $base =~ ^[0-9]+\ .*\.(ogg|wav)$ ]]; then
        echo "$src: Unexpected file name. Skipping..." >&2
        continue
    fi
    printf -v dest "$dir/%0${width}d ${base#* }" $((++n))
    echo "moving '$src' to '$dest'"
#   mv -n "$src" "$dest"
done
可以作为

./renum Folder*/*

假设脚本保存为
renum
。它只会打印出源文件名和目标文件名。要进行实际移动,应在确保其按预期工作后,将
放在行
#mv-n“$src”“$dest”
开头。请注意,
mv
命令不会由于
-n
选项而覆盖现有文件。这可能是可取的,也可能不是可取的。脚本将打印一条警告消息,并跳过意外的文件名,即文件名不符合问题中指定的模式。

使用带-print0 | sort-z的边读边查找循环我测试了第一次重命名一个没有导出c=0的行文,效果非常好。很好的一点是,这两种解决方案都对文件夹敏感:因此我可以在不同的文件夹名称上运行脚本:这非常有用,因为文件夹的名称包含我要按顺序编号的作品的名称。但是可能不止一部作品,比如说《哈姆雷特1…4》和《奥赛罗1…4》,像这样我就可以分别运行剧本了。非常感谢。没有
导出
,它正常工作,因为
c
是用perl创建的。我修改了答案。感谢您通过单击大复选标记来满足您的需要(✓) 在它旁边,也可以选择向上投票(向上投票需要至少15个信誉点)。如果您发现其他答案有帮助,请向上投票。接受和向上投票有助于未来的读者。请查看此脚本版本也非常方便:但有一件事:是否可以调整“%04d”-参数动态设置为文件数?因此,如果文件数小于10000,则为“%04d”;如果文件数小于1000,则为“%03d”。%02d小于100?@PeterStrawson是的,我为此编辑了脚本。
argc
是参数计数,
width
argc
中的小数位数。但是如果存在不符合模式的文件名(会在脚本中发出警告消息的文件名),这种简单的方法可能会失败在参数列表中。脚本也可能会遇到“参数列表太长”的问题错误。但这似乎包含脚本中的文件夹名称。这意味着每次使用都需要更改脚本。M.Nejat Aydin解决方案允许在执行脚本时调用文件夹名称。或者我在这里遗漏了什么?感谢您的精彩评论,我已更新了答案以给出目录/路径其中文件作为参数。
rename -n '
    do {
        use 5.012;
        state $c = 0;
        s@/\d+@sprintf "/%0.2d", ++$c@e
    }
' Folder*/*
find .  | (i=0; while read f; do 
let i+=1; mv "$f" "${f%/*}/$(printf %04d "$i").${f##*.}"; 
done)
./myscript Folder*/
./myscript Folder1/
./myscript Folder2/
./myscript .
#!/bin/bash

argc=$#
width=${#argc}

n=0
for src; do
    base=$(basename "$src")
    dir=$(dirname "$src")
    if ! [[ $base =~ ^[0-9]+\ .*\.(ogg|wav)$ ]]; then
        echo "$src: Unexpected file name. Skipping..." >&2
        continue
    fi
    printf -v dest "$dir/%0${width}d ${base#* }" $((++n))
    echo "moving '$src' to '$dest'"
#   mv -n "$src" "$dest"
done
./renum Folder*/*