如果 bash 中的文件夹名称以 4 位数字结尾,则递归重命名并在此处添加括号
rename recursively adding parenthere if folder name ending with 4 digits in bash
我一直在尝试递归重命名名称以四位数字结尾的文件夹。
例如,我有一个这样的文件夹名称:
this is the name 2004
我正在尝试将其重命名为:
this is the name (2004)
我尝试拆分名称的前缀和数字部分,但是我无法 mv
重命名这些文件夹。
这是我目前试过的代码:
#!/bin/bash
F=$(find . -name '*[0-9]' -type d)
for i in "$F";
do
R2=$(echo "$i" | awk '{print $NF}')
R1=$(echo "$i" | sed 's/.\{4\}$//')
R3=$(echo "$R2" | sed -r "s/(^[0-9]+$)/()/g")
mv "$i" "$R1 $R3"
# Even tried:
mv "\"$i"\" "\"$R2 $R3"\"
done
是否有人可以查看 or/and 提出一些指导以允许 mv
找到初始文件夹及其目的地?
以下命令:
find -name '*[0-9][0-9][0-9][0-9]' -type d -exec bash -c 'for dir; do mv "$dir" "${dir%[0-9][0-9][0-9][0-9]}(${dir#${dir%[0-9][0-9][0-9][0-9]}})"; done' - {} + -prune
应该可以。
- 双引号包围变量扩展
${dir%[0-9][0-9][0-9][0-9]}
删除最后 4 位数字后缀
${dir#${dir%[0-9][0-9][0-9][0-9]}}
删除前面的前缀
-exec bash -c '..' - {} +
-
跳过 -c command
之后的第一个参数,这是 [=16=]
所采用的,参见 man bash
/-c
-prune
在末尾以防止匹配时在子树中搜索,(假设 2004/2004
然后 mv 2004/2004 "2004/(2004)"
或 mv 2004/2004 (2004)/2004' 会失败)
我发现 Bash 在查找和重命名文件以满足所有转义文件的需要时很烦人。这是一个更干净的 Ruby 解决方案:
#!/usr/bin/ruby
require 'fileutils'
dirs = Dir.glob('./**/*').select {|x| x =~ / [0-9]*/ }
dirs.sort().reverse().each do |dir|
new_name=dir.gsub(/(.*)( )([0-9]{4})/, '()')
FileUtils.mv dir,new_name
end
当$F
有多个目录时,for循环会将其视为一个带有换行符的长条目(尝试echo "F=[$F]"
)。
同样使用 -depth
,你可能有 topdir 2004/subdir 2004
。所以首先重命名子目录。
当目录没有换行时,你可以试试
#!/bin/bash
while IFS= read -r orgdir; do
mv "${orgdir}" "$(sed -r "s/([0-9]+$)/()/g" <<< "${orgdir}")"
done < <(find . -depth -name '*[0-9]' -type d)
我一直在尝试递归重命名名称以四位数字结尾的文件夹。
例如,我有一个这样的文件夹名称:
this is the name 2004
我正在尝试将其重命名为:
this is the name (2004)
我尝试拆分名称的前缀和数字部分,但是我无法 mv
重命名这些文件夹。
这是我目前试过的代码:
#!/bin/bash
F=$(find . -name '*[0-9]' -type d)
for i in "$F";
do
R2=$(echo "$i" | awk '{print $NF}')
R1=$(echo "$i" | sed 's/.\{4\}$//')
R3=$(echo "$R2" | sed -r "s/(^[0-9]+$)/()/g")
mv "$i" "$R1 $R3"
# Even tried:
mv "\"$i"\" "\"$R2 $R3"\"
done
是否有人可以查看 or/and 提出一些指导以允许 mv
找到初始文件夹及其目的地?
以下命令:
find -name '*[0-9][0-9][0-9][0-9]' -type d -exec bash -c 'for dir; do mv "$dir" "${dir%[0-9][0-9][0-9][0-9]}(${dir#${dir%[0-9][0-9][0-9][0-9]}})"; done' - {} + -prune
应该可以。
- 双引号包围变量扩展
${dir%[0-9][0-9][0-9][0-9]}
删除最后 4 位数字后缀${dir#${dir%[0-9][0-9][0-9][0-9]}}
删除前面的前缀-exec bash -c '..' - {} +
-
跳过-c command
之后的第一个参数,这是[=16=]
所采用的,参见man bash
/-c
-prune
在末尾以防止匹配时在子树中搜索,(假设2004/2004
然后mv 2004/2004 "2004/(2004)"
或 mv 2004/2004 (2004)/2004' 会失败)
我发现 Bash 在查找和重命名文件以满足所有转义文件的需要时很烦人。这是一个更干净的 Ruby 解决方案:
#!/usr/bin/ruby
require 'fileutils'
dirs = Dir.glob('./**/*').select {|x| x =~ / [0-9]*/ }
dirs.sort().reverse().each do |dir|
new_name=dir.gsub(/(.*)( )([0-9]{4})/, '()')
FileUtils.mv dir,new_name
end
当$F
有多个目录时,for循环会将其视为一个带有换行符的长条目(尝试echo "F=[$F]"
)。
同样使用 -depth
,你可能有 topdir 2004/subdir 2004
。所以首先重命名子目录。
当目录没有换行时,你可以试试
#!/bin/bash
while IFS= read -r orgdir; do
mv "${orgdir}" "$(sed -r "s/([0-9]+$)/()/g" <<< "${orgdir}")"
done < <(find . -depth -name '*[0-9]' -type d)