Это работает, если Вы вставляете свой regex / /
(не знал, что Вы могли покончить с ними вообще), и удостоверьтесь, что замена заканчивается заключенная в кавычки:
system("echo "id "| awk '{sub(/\\.*0+$/,\""subst"\"); print}'");
Или:
system("echo "id "| awk '{sub(/"regex"/,\""subst"\"); print}'");
Но я не уверен, почему Вы просто не делаете:
sub(/\.*0+$/,"",id);
print id;
избегать что целый system
звонить.
С 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
когда счастливый).
Можно использовать 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'
Преимущества:
bash
или ksh93
**
позволяет),s/[^A-Za-z0-9 _-]/_/g
который заменяет все символы не в классе символов [A-Za-z0-9 _-]
--keep-old-files
к 2-му (GNU) смолят команду ;)
– maxschlepzig
25.02.2013, 00:37
Лучший способ приблизиться к этому состоит в том, чтобы определить допустимые символы и обходное перемещение для них вместо того, чтобы стремиться определить символы для перемещения. Это более сложно, чем просто определение ограниченного набора символов, который приемлем, потому что существуют определенные правила о том, что позволяется где в имени файла. По сути, это использует ограниченное подмножество, которое должно быть безопасно (насколько я могу сказать от чтения документов 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
если Вы хотите разрешение и делаете то, что оно производит.
**/*.pat
globbing. Но из-за основного цикла я все еще получаю одно ветвление/должностное лицо для каждого файла. С одной стороны, перекод () функция устраняет дополнительный вызов sed - но с другой стороны его довольно подробное - я имею в виду слишком подробный для использования его в интерактивном режиме на приглашении командной строки.
– maxschlepzig
24.02.2013, 20:17
bash
рекурсивный globbing следует за символьными ссылками.
– Stéphane Chazelas
24.02.2013, 22:36
cp -t dest-dir files
. Необходимо было бы создать каталоги, удалить -t
и добавьте --
. Кроме того, можно заменить Ваш recode
с ${file//[!...]/_}
.
– Stéphane Chazelas
24.02.2013, 23:47