我在这里要疯了。我有很多这样的文件夹
Folder 1/
Subfolder 2/
Item.01
Item.02
Subfolder 3/
Item.01
Item.02
我想递归且按顺序重命名文件夹 1 内的所有文件,但遵循当前层次结构(如 所示)ls
并将它们移动到平面结构(单个文件夹内的所有文件)。
例子:
Folder 1/
Item 01
Item 02
Item 03 (previously Item 01 on Subfolder 2)
Item 04 (previously Item 02 on Subfolder 2)
Item 05 (previously Item 01 on Subfolder 3)
这在 bash 上可能吗?非常感谢!
答案1
查看以下
globstar
选项如何bash
帮助您:shopt -s globstar ; for i in ** ; do echo "$i" ; done
这应该为您提供目录树中所有项目的排序列表,但它将包括文件和子目录的条目(行)。
过滤掉子目录:
shopt -s globstar ; for i in ** ; do [ -f " $i" ] && echo "$i" ; done
引入一个计数器,并删除当前文件后缀:
cnt=1 shopt -s globstar for i in ** ; do [ -f "$i" ] && echo "${i%%.*}.$cnt" cnt=$((cnt=cnt+1)) done
将测试语句替换
echo
为mv
您选择的:mv "$i" "${i%%.*}.$cnt"
(可选)
globstar
完成后取消设置该选项:`shopt +s globstar`
答案2
使用以下方法更容易zsh
:
autoload zmv # best in ~/.zshrc
cd "Folder 1"
n=0; zmv -n '**/Item.<->(#qn^/)' 'Item ${(l:2::0:)$((++n))}'
(高兴时删除-n
(用于空运行))。
<->
:任何十进制数字序列(<x-y>
无边界)(#qn)
:用于数字排序(所以Subfolder 10
来后Subfolder 2
)。^/
: 排除文件类型目录。${(l:2::0:)var}
:左填充(如果较大则截断), s 长度$var
为0
2。
警告注意事项:虽然 glob**/
旨在匹配任何级别的子目录,包括空级别,因此匹配当前目录中的文件,但zmv
它不会因为它对模式进行两次传递,一次到 glob 并第二次作为简单的模式匹配来提取捕获组(然后第二次**/Item
由于缺少而进行模式匹配/
)。
解决方法是使用:
zmv -n '(**/)Item.<->(#qn^/)' 'Item ${(l:2::0:)$((++n))}'
或者:
zmv -wn '**/Item.<->(#qn^/)' 'Item ${(l:2::0:)$((++n))}'
但随后zmv
检测到它是递归匹配并打开深度优先顺序(以便能够安全地重命名目录)。如果您不想深度优先排序并匹配当前目录中的文件,可以使用**/
( (*/)#
) 的长形式:
zmv -n '(*/)#Item.<->(#qn^/)' 'Item ${(l:2::0:)$((++n))}'
例子
在:
.
├── Subfolder 1
│ ├── Item.01
│ ├── Item.02
│ └── Subsubfolder
│ └── Item.01
├── Subfolder 10
│ ├── Item.01
│ └── Item.02
└── Subfolder 2
├── Item.01
└── Item.02
它给:
mv -- Subfolder\ 1/Item.01 Item\ 01
mv -- Subfolder\ 1/Item.02 Item\ 02
mv -- Subfolder\ 1/Subsubfolder/Item.01 Item\ 03
mv -- Subfolder\ 2/Item.01 Item\ 04
mv -- Subfolder\ 2/Item.02 Item\ 05
mv -- Subfolder\ 10/Item.01 Item\ 06
mv -- Subfolder\ 10/Item.02 Item\ 07