Что я хочу сделать, так это прочитать список имен файлов из индексного файла, а затем скопировать каждый из перечисленных файлов в другой каталог, но у меня возникли небольшие проблемы с правильным соединением xargs и cp.
head -n 150 ../indexes/index.txt | xargs cp ~/path/to/destination/
Это дает следующую ошибку:
cp: target 'foo.txt': Not a directory
где foo.txt
— это 150-е имя файла, указанное в index.txt. Очевидно, что cp должен принимать входные данные от xargs в качестве первого операнда, а не второго, но как мне заставить его это сделать?
🤔 А знаете ли вы, что...
С помощью Bash можно создавать и запускать скрипты для автоматизации повседневных задач.
xargs
имеет параметр -I
, который по сути позволяет вам указать шаблон замены и записать шаблон замены в команде (cp
, в вашем случае). Затем, когда команда выполняется, все экземпляры этого шаблона замены заменяются следующей строкой ввода. Итак, ваша командная строка должна выглядеть примерно так:
head -n 150 ../indexes/index.txt | xargs -I {} cp {} ~/path/to/destination/
Без -I
cp
просто видит вторую строку ввода как пункт назначения, что не предназначено.
Обновлять: Итак, разбивка происходящего:
Поскольку каждая строка ввода считывается из head
, поскольку вы настроили канал, вывод head
поступает в канал. Когда xargs
получает новую строку из канала, потому что вы указали ... -I {} cp {} ...
, вместо того, чтобы пытаться создать одну большую строку аргумента, состоящую из каждой строки ввода, и пытаться передать ее в cp
, он выполняет cp
, используя каждую строку ввода в качестве исходный операнд.
Чтобы объяснить немного дальше, рассмотрим этот сценарий. У нас есть файл с именем test.txt
, который содержит следующее:
some_file.txt
another_file.txt
a_third_file.txt
Теперь предположим, что мы хотим написать команду для копирования всех этих файлов в заданное место назначения. Если просто написать...
cat test.txt | xargs cp /path/to/destination
...тогда cp
эффективно видит следующее:
cp some_file.txt another_file.txt a_third_file.txt
В этой форме он пытается рассматривать a_third_file.txt
как каталог и копировать в него два предыдущих файла (поэтому в вашем случае cp
говорит, что 150-й путь не является каталогом). xargs -I {}
исправляет это:
cat test.txt | xargs -I {} cp {} ~/path/to/destination
Теперь, вместо того, чтобы cp
выполнялась только один раз, cp
выполняется три раза:
cp some_file.txt ~/path/to/destination
cp another_file.txt ~/path/to/destination
cp a_third_file.txt ~/path/to/destination