linux - 将子目录递归重命名为bash中的新模式
问题描述
我想将子目录重命名为我的新模式,但某些结果在我自己的脚本中可能很危险:
dst=$1
dirs=$( find $dst -type d )
for dir in $dirs; do
path=$( echo $dir | awk 'BEGIN{FS=OFS="/"}{NF--; print}' )
new_pattern=$( mkdir "$(head /dev/random | tr -dc A-Za-z0-9 | head -c 15 ; echo '')
mv -v $dir $path/$new_pattern
done
例如,如果我使用/tmp/etc
作为输入参数,我会在第一次迭代中得到令人讨厌的结果:
mv -v /tmp/etc /tmp/<newpattern>
所以在下一次迭代中不会有/tmp/etc
工作。
我的脚本中的第二个问题是当我使用相对路径etc
作为输入参数时。所以第一个输出是:
mv -v etc /<newpattern>
这是一个非常糟糕的做法。我理想的方法是检测所有目录,然后以我自己的模式递归地重命名它们。
更新
我的模式是:head /dev/random | tr -dc A-Za-z0-9 | head -c 15 ; echo ''
或者可能是其他任何东西。
所有目录都是空的,没有任何文件。然后我想根据我的模式将所有这些目录重命名为新名称。
dst=$1
dirs=$(find $dst -type d | sort -r)
for dir in $dirs; do
path=$( echo $dir | awk 'BEGIN{FS=OFS="/"}{NF--; print}' )
new_pattern=$(head /dev/random | tr -dc A-Za-z0-9 | head -c 15 ; echo '')
mv -v $dir $path/$new_pattern
done
在输入参数中使用相对路径时:
# pwd
/tmp
# bash a.sh etc
renamed 'etc/apache2/conf-enabled' -> 'etc/apache2/6jFtEeT27SHre1t'
renamed 'etc/apache2' -> 'etc/0rP0r7p63CzICdE'
renamed 'etc/alternatives' -> 'etc/I3Yog16F2ijlcYe'
renamed 'etc' -> '/zKpmJT351VuDrVK'
最后一个输出renamed 'etc' -> renamed 'etc' -> '/zKpmJT351VuDrVK'
是主要问题。
解决方案
你可以跑到find -depth
总是在他们的父母之前访问子目录。
您的代码有许多不同的问题,这些问题会导致它在任何重要的文件名上失败。
dirs=$( find $dst -type d )
这会导致包含由;dirs
输出的标记。find
但是如果这些文件名中的任何一个包含空格,这将导致多个标记,如果您尝试循环访问此变量,这些标记随后将被错误地解释为单独的文件名。同样,如果任何文件名包含 shell 元字符(如引号或通配符),您的下游代码要么会中断,要么需要非常复杂才能解决此问题。
(当然,由于引用错误,循环内的代码也会因类似原因而失败。)
到目前为止,最简单的解决方法是find -exec
改用。
find "$1" -depth -type d -exec sh -c 'for dir; do
path=${dir%/*}
new_pattern=$(head /dev/random | tr -dc A-Za-z0-9 | head -c 15)
mv -v "$dir" "$path/$new_pattern"
done' _ {} +
这里的关键修复是find
知道如何将正确引用的所有内容传递给,-exec ... {}
因此您不必担心那部分。只需确保始终在内部的参数周围使用双引号,-exec sh -c '...'
以避免破坏find
已经完成的良好工作。(在没有明确论证的情况下,for dir
表示for dir in "$@"
。)
我还切换到参数扩展以避免不必要的 Awk 调用。echo
还要注意在命令替换结束时不需要任何东西,因为 shell 无论如何都会修剪最后的换行符。(可能会切换到/dev/urandom
以避免耗尽您的/dev/random
资源。它可以正常工作一段时间,但是一旦您在几百个文件上运行它,它就会开始阻塞,因为随机数生成器需要收集更多的熵。随机性来自urandom
较少的随机性,但对于这个特定的用例来说可能已经足够了。)
http://mywiki.wooledge.org/UsingFind对与该领域常见的初学者错误相关的各种问题进行了广泛的处理。整个网站更好的部分是关于引用问题。
推荐阅读
- docker - 运行 Docker nginx 找不到复制的文件
- postgresql - sqlalchemy 无法在 for 循环中执行 session.add()
- bootstrap-table - 引导表不适用于 RouterLink
- javascript - 在 Golang/Gin 模板中运行 Vue 应用程序
- android - 我如何在颤动中创建一个绘图应用程序,我可以在颤动中绘制线条形状
- python - scipy.stats.binom 和 np.random.binomial 之间的区别
- angular - Primeng virtualscroll offset 像 peagination
- android - Cordova 媒体插件 - 加载本地文件/blob - 错误代码“未定义”
- javascript - 我正在尝试让不和谐的机器人收到此错误 [Symbol(code)]: 'BITFIELD_INVALID'
- python - “返回”值的作用和程序的意外结果