首页 > 解决方案 > 将子目录递归重命名为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'是主要问题。

标签: linuxbashawksedgrep

解决方案


你可以跑到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对与该领域常见的初学者错误相关的各种问题进行了广泛的处理。整个网站更好的部分是关于引用问题。


推荐阅读