У меня есть список файлов, разделенных пробелами в файле list.txt
. Я хотел бы скопировать их в новую папку.
Я пытался сделать:
cp `cat list.txt` new_folder
но это не сработало.
Как бы вы это сделали?
Обновить:
Спасибо за все ваши очень интересные ответы. Я не так много просил :)
После того, как вы попробовали решение выше во второй раз, кажется, что cp
напечатали справку по использованию, потому что папка new_folder
еще не существовала! Извините, это кажется глупой ошибкой ... Когда я создаю папку раньше, она работает.
Тем не менее, я многому научился из всех ваших ответов и решений, спасибо за то, что вы потратили время на их написание.
Ответы:
Попробуйте использовать xargs:
Обновить:
Я сделал это на OS X, версия которого отличается от версии GNU / Linux. То,
xargs
что исходит от GNU findutils , не имеет,-J
но имеет-I
аналогичное (как отметил Деннис Уильямсон в комментарии). Версия Xargs для OS X имеет и то,-I
и другое и-J
немного отличается по поведению - либо подойдет для этого оригинального вопроса.источник
xargs
нет-J
этого,-I
который, кажется, делает то же самое. Какая версияxargs
и какая у вас ОС / дистрибутив?xargs --version
возвращает сообщение об ошибке использования. Это скорее всего BSD-версия xargs. Использование-I
и-J
тонко отличаются. Я обновлю свой ответ с хорошо отформатированными примерами.-J
и-I
:)Нет необходимости
cat
вообще:Или используя длинные опции:
Вот несколько версий оболочки. Обратите внимание, что некоторые переменные не заключены в кавычки или
for
циклы используются специально, потому что OP указал, что имена файлов разделены пробелом. Некоторые из этих методов не будут работать для ввода имени файла на строку, в котором имена файлов содержат пробелы.Bash:
или
ш (или Баш):
или
или
или
источник
-t
нуженxargs -a list.txt cp -t new_folder
?-t
это вариантcp
. Он копирует все исходные аргументы в указанный целевой каталог. Здесь он позволяет указать цель перед источником, добавляемымxargs
командой.Раньше у меня был смущающий круговой ответ здесь, но ответ Дениса напомнил мне, что я пропустил самую основную вещь. Итак, я удалил свой оригинальный ответ. Но так как никто не сказал эту самую основную вещь, я думаю, что это стоит поместить здесь.
Исходный вопрос: «У меня есть текстовый файл со списком разделенных пробелами имен файлов. Как я могу скопировать их в один целевой каталог». Сначала это может показаться сложным или сложным, потому что вы думаете, что вам нужно каким-то образом извлечь элементы из файла определенным образом. Тем не менее, когда оболочка обрабатывает командную строку, первое, что она делает, - разделяет список аргументов на токены и (это бит, который никто не сказал прямо) пробелами отдельные токены . (Новые строки также разделяют токены, поэтому тест Дуга Харриса со списком, разделенным новой строкой, дал тот же результат.) То есть оболочка ожидает и уже может обрабатывать разделенный пробелами список.
Поэтому все, что вам нужно сделать, это поместить разделенный пробелами список (который у вас уже есть) в нужное место в вашей команде. Ваша команда является некоторым вариантом этого:
Единственная проблема заключается в том, что вы хотите получить список файлов с 1 по # из вашего текстового файла.
Как отмечает Деннис в своем комментарии, ваша первоначальная попытка (
cp
cat list.txtnew_folder
) уже сработала Зачем? Поскольку внутренняя командаcat list.txt
сначала обрабатывается оболочкой и расширяется в нееfile1 file2 file3...file#
, это именно то, что оболочка ожидает и хочет в этой части команды. Если это не сработало, либо (1) у вас была опечатка, либо (2) ваши имена файлов были как-то странными (в них были пробелы или другие необычные символы).Причина того, что все ответы Денниса работают, заключается в том, что они предоставляют необходимый список файлов для
cp
работы, помещая этот список во все команды. Опять же, сама команда имеет следующую структуру:Легко увидеть, как все это объединяется в этой версии:
$()
заставляет оболочку запускать команду в круглых скобках, а затем подставлять ее вывод в эту точку в большей строке. Затем оболочка запускает линию в целом. Кстати,$()
это более современная версия того, что вы уже делали с обратными галочками (`). Далее:<
оператор перенаправления файлов. Он говорит оболочке вывести содержимоеlist.txt
в стандартный ввод. Поскольку$()
бит обрабатывается первым, вот что происходит поэтапно:cp $(<list.txt) new_folder
# split line into three tokens: cp, $(<list.txt), new_folder
cp file1 file2 file3...file# new_folder
# substitute result of $(<list.txt) into the larger command
Очевидно, шаг 2 - просто нормальная
cp
команда, которую вы хотели.Я понимаю, что много бью эту (возможно, очень мертвую) лошадь, но думаю, это стоит того. Понимание того , как оболочка обрабатывает команду, может помочь вам написать ее лучше и значительно упростить. Это также покажет вам, где проблемы могут скрываться. В этом случае, например, мой первый вопрос к вам должен был быть о забавных именах файлов или возможной опечатке. Никакой акробатики не было необходимости.
источник
--parents
флаг. Вы можете сделать это многословным-v
для записи того, что было скопировано. Если вы хотите сохранить права доступа, вам нужен флаг-a
или-p
. Т.е.,cp --parents -av $(<list.txt) new_folder
. Все это при условии, что ваш список файлов действительно является всеми файлами, в противном случае вам также может понадобиться-r
флаг для рекурсии.--parents
флага там не существует. Их (производная от BSD) версия предоставляетcp
только короткие опции, а не длинные опции в стиле GNU. Для стиля BSDcp
флаг для рекурсивного копирования - прописные-R
, а не строчные.