用Bash中的一个衬里重命名目录及其子目录

时间:2019-05-27 21:58:02

标签: bash

我有一个反编译的android应用,我正在编写脚本来重命名目录。

在反编译文件夹内是一个路径:

smali/com/FOLDER/SUB-FOLDER

我要将现有文件夹重命名为:

smali/com/NEW-NAME/SUB-NEW-NAME

我当时以为我可以使用mv命令,但是在手册页中进行挖掘似乎无法完成。我正在尝试:

mv smali/com/FOLDER smali/com/FOLDER/SUB-FOLDER -t smali/com/NEW-NAME/SUB-NEW-NAME

这仅适用于将多个文件移动到单个目标位置。

编辑:

现有文件夹:

  smali/com/FOLDER/SUB-FOLDER 

我试图重命名两个文件夹,同时保留每个文件夹的内容。

每个文件夹重命名的示例为:

mv smali/com/FOLDER/ smali/com/NEW-NAME
mv smali/com/NEW-NAME/SUB-FOLDER smali/com/NEW-NAME/SUB-NEW-NAME

3 个答案:

答案 0 :(得分:1)

这是一个非常琐碎的单行代码;例如:

intersect(df$UT, intersect(df$MT, df$HT))
[1] "ABO"        "AC009234.1" "ADAMTS15" 

...当然,假设您首先运行适当的函数定义。如果您只想重命名rename_pieces smali/com/FOLDER/SUB-FOLDER smali/com/NEW/SUBNEW ,则在创建SUB-FOLDER后应该不存在它,它看起来像:

NEW-NAME

...而且,这很可能是您真正想要的行为,而不是任何其他解释,只要它使rename_pieces() { local old=$1 new=$2 [[ $new = */* ]] && mkdir -p -- "${new%/*}" mv -T -- "$old" "$new" } 的内容不为 FOLDER和原始名称。


相比之下,如果您真的想要重命名两个目录,则将变得更加有趣。如果我们保证源和目标的深度相同,则可能看起来像这样:

SUB-FOLDER

此后:

log_or_run() {
  if [[ $log_only ]]; then   # just log what we would run
    printf '%q ' "$@" >&2    # use printf %q to generate a safely-escaped version
    printf '\n' >&2          # ...and terminate with a newline.
  else
    "$@"                     # actually run the command
  fi
}
rename_pieces() {
  local old=$1 new=$2 common
  while [[ ${old%%/*} = "${new%%/*}" ]]; do
    common+=/"${old%%/*}"
    old=${old#*/}; new=${new#*/}
  done
  while [[ $old && $new ]]; do
    log_or_run mv -T -- "${common#/}/${old%%/*}" "${common#/}/${new%%/*}"; echo
    common+=/"${new%%/*}"
    [[ $old = */* && $new = */* ]] || return
    old=${old#*/}; new=${new#*/}
  done
}

...在输出中发出:

log_only=1 rename_pieces smali/com/FOLDER/SUB-FOLDER smali/com/NEW/SUBNEW

...并且实际上在没有mv -T -- smali/com/FOLDER smali/com/NEW mv -T -- smali/com/NEW/SUB-FOLDER smali/com/NEW/SUBNEW 的情况下也会运行这些命令。

答案 1 :(得分:0)

想不出任何更优雅的方法,但是以下方法应该起作用: find . -path '.*com/FOLDER/SUBFOLDER' | awk '{new_dir=$1; sub("/FOLDER/SUBFOLDER","/NEW/SUBNEW", $new_dir); printf("mkdir -p %s\nmv %s %s\n", $new_dir, $1, $new_dir);}' > cmds

这将在mv文件中获取所有必需的cmds命令。验证它是正确的,然后使用sh cmds执行。尽管这并不是最有趣,但是在处理重要数据时我还是喜欢这种方法,因为验证您要运行的数据总是更好。

编辑:修复了注释中指出的有关脚本不创建目录(如果目录不存在)的问题。

答案 2 :(得分:0)

好吧,我会咬...

如果您只需要一根衬板,则可以随时使用AND_IF命令&&将多行转换为一行。

mv ./FOLDER ./NEW-NAME && mv ./NEW-NAME/SUB-FOLDER ./NEW-NAME/SUB-NEW-NAME

这具有附加的效果,即只有在父级重命名成功后,子文件夹的重命名才会发生。

但是首先移动子文件夹不是更有意义吗?让我们为from标签分配两个变量$f,为to分配两个变量$t。这些可以一行执行,但是当我们想要再次更改时,这种方式更容易。

f=FOLDER; t=NEW-NAME;
mv "./$f/SUB-$f" "./$f/SUB-$t" && mv "./$f" "./$t"

其余所有示例均假设已设置from和to变量。

$p分配给父查找,$s分配给所有匹配的子文件夹,以确保它们都存在。这个示例以及上面的所有示例仍然都是纯BASH解决方案。

p=(./*$f); [[ -d $p ]] && for s in $p/*$f; do mv "$s" "${s%$f}$t"; done && mv "$p" "${p%$f}$t"

要考虑的另一种方法是使用find,就像在此衬纸中一样。

find . -d -type d -name "*$f" -execdir sh -c 'mv -- "$0" "${0%$1}$2"' "{}" "$f" "$t" \;

这只会重命名匹配的文件夹,但会在所有子文件夹中查找匹配项,如果使用不同的起点,则使用-maxdepth 2限制遍历深度,或者添加-mindepth进行校准。

nJoy!