Чтобы перебрать список имен файлов с одним именем в строке, у вас есть несколько возможностей:
Используйте подстановку команд, чтобы превратить файл в список имен файлов внутри оболочки. Вы должны принять меры предосторожности, потому что вы не можете поместить подстановку команд в двойные кавычки, так как результат подстановки команд должен быть разбит на слова. Вам нужно отключить глобализацию и настроить IFS
на разделение слов только на новые строки.
set -f; IFS='
'
scp -- $(…) remote.example.com:
Используйте встроенное read
для обработки имен файлов в цикле. Опять же, вы должны быть осторожны, потому что read
обрабатывает обратную косую черту и символы $IFS
специально.
… | while IFS= read -r x; do scp -- "$x" remote.example.com: done
Вы можете использовать GNU xargs, но вы должны действовать осторожно, потому что xargs ожидает его ввода в странно заключенном в кавычки формате. Вы должны передать опцию -d '\n'
чтобы явно выбрать переводы строки в качестве разделителя ввода и отключить специальное поведение пробелов и \'"
.
… | xargs -d '\n' -I {} scp {} remote.example.com:
Единственное преимущество xargs
заключается в том, что он может сгруппировать несколько аргументов в один вызов до предела длины командной строки, но это работает, только если аргументы передаются команде в последнюю очередь. Вы можете достичь этого с помощью промежуточного вызова sh
, но это редко стоит того.
… | xargs -d '\n' sh -c 'scp -- "$@" "$0"' remote.example.com:
Более простой способ использования xargs
- получить разделенный нулями список вместо разделенных строкой . Для этого требуется опция -0
, которая поддерживается GNU xargs, а также недавним * BSD. Как и выше, приведение аргументов в не финальную позицию требует небольшой работы.
… | tr '\n' '\0' | xargs -0 sh -c 'scp -- "$@" "$0"' remote.example.com:
…
Часть будет выглядеть как grep NAME_REGEXP /path/to/filenames.list
если вы хотите фильтровать имена файлов с помощью регулярного выражения. Если вы хотели отфильтровать содержимое файла, используйте один из методов, приведенных выше, для передачи имен файлов в grep
, например:
set -f; IFS='
'
scp -- $(grep -l CONTENT_REGEXP -- $(cat /path/to/filenames.list)) \
remote.example.com:
Другая возможность, которая обходит трудности оболочки, - это использовать rsync
и его --files-from
. Предполагая, что имена файлов все относительно текущего каталога:
grep NAME_REGEXP /path/to/filenames.list |
rsync -a --files-from - . remote.example.com: