我知道您可以使用以下内容重命名单个文件夹中的所有文件名:
$parsed = preg_split('/\s+/',$string);
$page_is = array_shift($parsed_url);
$getVars = array();
foreach($parsed as $argument) {
list($variable,$value) = explode("=",$argument); $getVars[$variable] = $value;
}
但是,有没有办法在多个文件夹中执行此操作?例如,它将搜索当前目录中的所有文件夹并进行更改。
我有for file in 1_*; do
mv "$file" "${file/1_/}"
done
版本4.3
答案 0 :(得分:1)
一个强大的解决方案,假设你有 GNU 或 BSD / OSX find
:
find . -type f -name '1_*' -execdir sh -c 'echo mv -- "$1" "${1#1_}"' _ {} \;
注意:
- 为了安全,这只会回显 mv
命令;删除echo
以执行实际重命名
- OP的替换,"${file/1_/}"
已更改为符合POSIX的"${file#1_}"
,实际上更接近意图。
- 如果您确实需要"${file/1_/}"
替换,系统上的sh
可能支持或不支持,则最好显式调用已知支持它的shell ,例如bash
- 符号链接被忽略(文件和目录);使用find -L ...
包含它们(作为要重命名的潜在文件,并使find
下降到符号链接到目录)。
功能
find . -type f -name '1_*'
在当前目录(-type f
)子树中查找名称与1_*
(-name '1_*'
)匹配的所有文件(.
)。< / LI>
-execdir
执行传递给它的命令在当前文件所在的子目录中。sh -c 'echo mv -- "$1" "${1#1_}"' _ {} \;
调用默认shell(sh
):
-c
)
mv -- "$1" "${1#1_}"
有效地从第一个位置参数(1_
)表示的文件名中删除前缀$1
。_
(sh
将分配给$0
,此处不感兴趣){}
,shell将绑定到$1
; \;
只会终止-execdir
的论点。请注意,--
可确保恰好以-
开头的任何文件名都不会被mv
误认为是选项(在下面类似地适用)。
-execdir
不符合POSIX标准;如果符合POSIX的变体因此更麻烦:
find . -type f -name '1_*' -exec sh -c \
'cd -- "${1%/*}" && f=${1##*/} && echo mv -- "$f" "${f#1_}"' _ {} \;
cd -- "${1%/*}"
更改手头文件所在的目录。
cd -- "$(dirname -- "$1")"
通常更强大,但效率更低;由于我们知道$1
始终是路径而不是此方案中的纯文件名,因此我们可以使用效率更高的cd -- "${1%/*}"
。f=${1##*/}
从文件路径中提取纯文件名。效果记录:
上述解决方案简洁,但效率低下,因为必须为每个匹配的文件生成一个shell实例。
潜在加速是使用peak's approach的变体,但只有在while
循环中避免调用外部实用程序时才使用 (mv
除外):
find . -type f -name '1_*' | while IFS= read -r f; do
new_name=${f##*/} # extract filename
new_name=${new_name#1_} # perform substitution
d=${f%/*} # extract dir
echo mv -- "$f" "$d/$new_name" # call mv to rename
done
以上承担了使用嵌入换行符打破文件名的假设风险(非常罕见);使用GNU或BSD find
,可以解决这个问题。
使用这种方法,只会生成单个 shell实例,它会在循环中处理所有匹配的文件名 - 只要在中外部实用程序在循环为mv
,这通常会比仅find
的{{1}}解决方案更快。
答案 1 :(得分:1)
如果你不想依赖太多细微之处,可以考虑一下这种非常行人的做法,假设有一个类似bash的shell,并且所有常见的嫌疑人(发现,sed,......)都可以直接使用:< / p>
find . -type f -name "1_*" | while read -r file ; do
x=$(basename "$file")
y=$(sed 's/1_//' <<< "$x")
d=$(dirname "$file")
mv "$file" "$d/$y"
done
(您可能希望使用“mv -i”或“echo mv ....”尝试此操作。您可能还希望将find
与-follow
选项一起使用。)