Как скопировать список файлов и скорректировать целевые имена файлов на лету?

Это работает, если Вы вставляете свой regex / / (не знал, что Вы могли покончить с ними вообще), и удостоверьтесь, что замена заканчивается заключенная в кавычки:

system("echo "id "| awk '{sub(/\\.*0+$/,\""subst"\"); print}'");

Или:

system("echo "id "| awk '{sub(/"regex"/,\""subst"\"); print}'");

Но я не уверен, почему Вы просто не делаете:

sub(/\.*0+$/,"",id);
print id;

избегать что целый system звонить.

2
24.02.2013, 12:09
3 ответа

С pax как найдено на Debian, SuSe, OpenBSD, NetBSD, по крайней мере:

find . -type f -name '*.pat' -print0 | pax -0rws'/?/_/gp' /path/to/dest/

pax стандартная утилита (вопреки tar или cpio), но -0 опция не, хотя может быть найден в нескольких реализациях.

Если существует оба a ?.pat и _.pat файлы, они закончат замененные тем же именем, таким образом, каждый перезапишет другой в месте назначения. То же, если существует a _ и ? каталог, их содержание будет объединено в _ каталог в месте назначения.

С GNU sort и GNU uniq, можно проверить на конфликты заранее с:

find . -type f -name '*.pat' -print0 |
  tr '?' _ |
  sort -z |
  uniq -zd |
  tr '\0' '\n'

Который сообщил бы о конфликтующих файлах (но не каталоги).

Вы могли использовать zsh zmv который заботился бы о конфликтах, но это будет все еще означать тот mkdir и один cp на файл:

autoload zmv
mkdir-and-cp() {mkdir -p -- $3:h && cp $@}
zmv -n -Qp mkdir-and-cp '(**/)*.pat(D.)' '/path/to/dest/$f:gs/?/_/'

(удалите -n когда счастливый).

3
27.01.2020, 21:53

Можно использовать tar GNU для него:

$ find -type f -name '*.pat' -print0  | tar -c -f - --null --files-from - \
    | tar -C /path/to/dest -v -x -f - --show-transformed --transform 's/?/_/g'

Преимущества:

  • только 3 ветвления/должностных лица необходимы (независимые от количества файлов)
  • выбор исходных файлов очень гибок - можно использовать полную мощность (GNU), находят для того (т.е. когда необходимо быть более конкретными, чем простая оболочка globbing как bash или ksh93 ** позволяет),
  • это также безопасно для имен файлов, содержащих новые строки
  • часть преобразования очень гибка, также - например, можно использовать что-то как s/[^A-Za-z0-9 _-]/_/g который заменяет все символы не в классе символов [A-Za-z0-9 _-]
3
27.01.2020, 21:53
  • 1
    +1 Хорошее решение, но обработка возможных конфликтов имени файла не рядом ни с одним. Однако без специальной утилиты (считающий записанных в, например, Python), я боюсь, что нет никакого более оптимального варианта, чем цикл оболочки с проверкой. –  peterph 24.02.2013, 21:40
  • 2
    @peterph, Вы могли добавить --keep-old-files к 2-му (GNU) смолят команду ;) –  maxschlepzig 25.02.2013, 00:37
  • 3
    Несомненно, но Вы обычно хотите некоторое распечатанное сообщение об ошибке, или даже автоволшебство переименовывают для случая в этих случаях. –  peterph 25.02.2013, 00:43

Лучший способ приблизиться к этому состоит в том, чтобы определить допустимые символы и обходное перемещение для них вместо того, чтобы стремиться определить символы для перемещения. Это более сложно, чем просто определение ограниченного набора символов, который приемлем, потому что существуют определенные правила о том, что позволяется где в имени файла. По сути, это использует ограниченное подмножество, которое должно быть безопасно (насколько я могу сказать от чтения документов FAT32). Что-то вроде этого должно работать (bash4 +):

#!/bin/bash

shopt -s globstar nullglob

for file in **/*.pat; do
    echo cp -t "${1:-.}" "${file//[![:alnum:].\-_\/]/_}"
done

Это возвратит что-то вроде этого:

$ > bar\?.pat
$ > baz\*.pat
$ > foo.pat
$ ./script foo
cp -t baz*.pat foo/baz_.pat
cp -t bar?.pat foo/bar_.pat
cp -t foo.pat foo/foo.pat

Передайте dir для копирования в как первый аргумент. Удалите вызов к echo если Вы хотите разрешение и делаете то, что оно производит.

1
27.01.2020, 21:53
  • 1
    Хорошо, с проблемой IFS имеют дело через a **/*.pat globbing. Но из-за основного цикла я все еще получаю одно ветвление/должностное лицо для каждого файла. С одной стороны, перекод () функция устраняет дополнительный вызов sed - но с другой стороны его довольно подробное - я имею в виду слишком подробный для использования его в интерактивном режиме на приглашении командной строки. –  maxschlepzig 24.02.2013, 20:17
  • 2
    Остерегайтесь этого bash рекурсивный globbing следует за символьными ссылками. –  Stéphane Chazelas 24.02.2013, 22:36
  • 3
    Обратите внимание, что синтаксис cp -t dest-dir files. Необходимо было бы создать каталоги, удалить -t и добавьте --. Кроме того, можно заменить Ваш recode с ${file//[!...]/_}. –  Stéphane Chazelas 24.02.2013, 23:47

Теги

Похожие вопросы