Объединить xargs -I с sed

Объединить xargs -I с sed

Я хочу использовать find для поиска определенных файлов, а затем использовать xargs с cp и sed для перемещения этих файлов в другую папку и переименования их. Я знаю, как сделать это в цикле, но это не то, что я ищу.

Я пытался:

find ${FOLDER} -iname "*${SOME_STRING}*" | xargs -I {} cp {} $(echo {} | sed 's/ABC/XYZ/g')

Почему это не работает и какое может быть решение?

решение1

Попробуйте это. Это не нужно xargs, просто find, sedи copy. Это не изменит никаких файлов, новолявывести список команд оболочки для копирования файлов. Так что если вам нравятся команды, которые она печатает, то вы запускаете ее снова и удаляете перед #в sh -xпоследней строке и позволяете оболочке выполнять команды.

find "${FOLDER:-.}" -iname "*${SOME_STRING:-ABC}*" |
sed "
    s/^/'/                      # surround filename with single quotes
    s/$/'/
    h                           # save filename in the sed hold space
    s/ABC/XYZ/g                 # change filename
    H                           # append to hold space (separates with newline)
    g                           # get original and modified from hold
    s/\n/ /g                    # replace the newline with a space
    s/^/cp -i/                  # make it into a copy command
"  #| sh -x                     # optionally pipe to shell

Почему этот подход лучше, чем xargsв этом случае? Потому что этот метод запускает всего 3 процесса ( find, sed, и sh) в дополнение к требуемой cpкоманде для каждого файла.

Для использования xargsобработки каждого имени файла потребуется больше процессов, чем требуется для одной cpкоманды.

Гораздо эффективнее позволить одному вызову sed сгенерироватьвсекоманд cp, чем вызывать новый sedпроцесс для каждого имени файла.

решение2

С использованием GNU Parallel это выглядит так:

find ${FOLDER} -iname "*${SOME_STRING}*" |
  parallel cp {} '{= s/ABC/XYZ/g =}'

Конструкция {= =} содержит выражение Perl, которое изменяет $_.

Одним из преимуществ является то, что GNU Parallel делает правильные вещи, даже если у вас есть файлы с именами:

My brother's 12" records worth >100$.txt

или ужасы вроде:

touch Y-"$(perl -e 'print pack("c*",1..9,11..46,48..255)')"

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