Как мне сделать замену на `$0`, но сохранить старое значение?

Как мне сделать замену на `$0`, но сохранить старое значение?

Я пытаюсь переименовать все файлы, начинающиеся с «m», чтобы они имели то же имя, за исключением того, что первый символ (или «m» в данном случае) удален.

Моя стратегия такова:

  1. Список всех файлов, сls
  2. Фильтр для тех, которые мне нужны, сegrep
  3. Сгенерируйте строку, которая мне не нужна, рядом с той, которая мне нужна, разделив их пробелом, awkнапример,mfoo foo
  4. Подать 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), так как gsubfunc ее затирает. Затем мы объединяем старую и новую, чтобы получить строку, которую мы хотим отправить, xargsкоторая затем будет вызвана mvс правильными аргументами для осуществления переименования.

решение3

Лучшая стратегия — использовать renameкоманду.

Обратите внимание, что точный синтаксис этих команд зависит от дистрибутива, обратитесь к manстранице вашей конкретной версии дистрибутива. В Ubuntu, например, с реализацией Perl rename, вы можете использовать регулярное выражение:

rename -nono 's/^m//' m*

Примечание: снимите -nonoфлаг, чтобы фактически выполнить переименование.

Связанный контент