Я пытаюсь переименовать все файлы, начинающиеся с «m», чтобы они имели то же имя, за исключением того, что первый символ (или «m» в данном случае) удален.
Моя стратегия такова:
- Список всех файлов, с
ls
- Фильтр для тех, которые мне нужны, с
egrep
- Сгенерируйте строку, которая мне не нужна, рядом с той, которая мне нужна, разделив их пробелом,
awk
например,mfoo foo
- Подать
xargs
вmv mfoo foo
Некоторые вопросы:
- Хорошая ли это стратегия?
- Что лучше?
Я застрял на шаге 3, ниже я расскажу, как я подошел к решению этой проблемы.
Я работаю в следующем каталоге:
$ find .
.
./cat
./mbar
./mbaz
./mfoo
Я могу быстро получить 1-2:
$ ls | egrep '^m'
mbar
mbaz
mfoo
Шаг 3 сложнее. Я использовал gsub
вторую нужную мне строку, чтобы сгенерировать ее, но не уверен, как «склеить ее с исходным значением, разделенным пробелом»:
$ ls | egrep '^m' | awk '{ gsub(/^./, ""); print }'
bar
baz
foo
Шаг 4 кажется мне логичным, хотя я не уверен, как закончить Шаг 3, поэтому я пока не могу его закончить. Ниже приведен один пример того, как, по моему мнению, это должно работать:
$ echo mfoo foo | xargs mv
$ find .
.
./cat
./foo
./mbar
./mbaz
Думаю, я близок, мне просто нужно узнать, как сохранить старое значение и напечатать его рядом со значением gsubed. Я попробовал следующий небольшой пример, но он не работает:
$ echo mfoo | awk '
pipe quote> { old = $0 }
pipe quote> { new = gsub(/^./, "") }
pipe quote> { print $old " " $new }'
awk: illegal field $(mfoo), name "old"
input record number 1, file
source line number 4
- Как мне сделать замену,
$0
сохранив старое значение? - Почему возникает эта ошибка?
решение1
Это должно справиться со всей операцией:
for file in m*; do mv "${file}" "${file#m}"; done
Прежде чем запустить это, проверьте сначала все с помощью
for file in m*; do echo mv "${file}" "${file#m}"; done
Здесь используется m*
глоб для шагов 1 и 2, затем ${file#m}
(который удаляет «m» из начала ${file}
) для шага 3 и, наконец, цикл для шага 4.
Чтобы ответить на ваш вопрос по AWK, можно сделать следующее:
echo mfoo | awk '{ print $0, substr($0, 2) }'
Переменные AWK не используют $
, это только для полей; отсюда и ваша ошибка: AWK понимает $old
как «значение поля, пронумерованного в соответствии со значением old
». Также будет легче читать, если вы поместите свои команды в один блок (предполагая, что они имеют один и тот же шаблон). Исправление вашего скрипта дает
echo mfoo | awk '{ old = $0; gsub(/^./, ""); print old, $0 }'
решение2
ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -l -t mv
Posix-lyреализация осуществляется через -L
опцию xargs
как:
ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -L 1 -t mv
ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); print x, $0 }' | xargs -L 1 -t mv
На основании чегоя ответилна ваш предыдущий вопрос относительно xargs
, мы можем использовать эти знания с пользой в этом примере.
Я немного изменил ваш awk
код: он сохраняет исходную строку ( $0
), так как gsub
func ее затирает. Затем мы объединяем старую и новую, чтобы получить строку, которую мы хотим отправить, xargs
которая затем будет вызвана mv
с правильными аргументами для осуществления переименования.
решение3
Лучшая стратегия — использовать rename
команду.
Обратите внимание, что точный синтаксис этих команд зависит от дистрибутива, обратитесь к man
странице вашей конкретной версии дистрибутива. В Ubuntu, например, с реализацией Perl rename
, вы можете использовать регулярное выражение:
rename -nono 's/^m//' m*
Примечание: снимите -nono
флаг, чтобы фактически выполнить переименование.