Переименовать каталог и его подкаталог с одним вкладышем в Bash - PullRequest
1 голос
/ 28 мая 2019

У меня есть приложение для 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

Это работает только для перемещения нескольких файлов в одно место назначения.

EDIT:

Существующие папки:

  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 ]

1 голос
/ 28 мая 2019

Это совершенно тривиальный однострочный; например:

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

... и, действуя аналогично без log_only=1, на самом деле запускает эти команды.

0 голосов
/ 05 июня 2019

Хорошо, я укушу ...

Если все, что вам нужно, это один вкладыш, вы всегда можете использовать команду AND_IF &&, чтобы превратить несколько строк в одну.

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

Это дает дополнительный эффект, что переименование подпапки будет происходить только в случае успешного переименования родительского элемента.

Однако не имеет ли больше смысла сначала перемещать подпапки?Позволяет назначить две переменные $f для метки from и $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!

0 голосов
/ 28 мая 2019

Не могу придумать ничего более изящного, но должно работать следующее: 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.Хотя это и не самое забавное, мне нравится такой подход при работе с важными данными, потому что всегда лучше проверить, что вы собираетесь запускать.

Редактировать: Исправлена ​​проблема, указанная в комментариях оскрипт не создает каталог, если он не существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...