Список копии файлов

У меня есть список файлов, разделенных пробелами в файле list.txt. Я хотел бы скопировать их в новую папку.

Я пытался сделать:

cp `cat list.txt` new_folder

но это не работало.

Как Вы сделали бы это?

Обновление:

Спасибо за все Ваши очень интересные ответы. Я не попросил так очень :)

Попробовав решение выше второго раза, это кажется этим cp распечатанный справка использования, потому что папка new_folderеще не существовал! Извините, это, кажется, глупая ошибка... Когда я создаю папку прежде, она работает.

Однако я узнал о многом из всех Ваших ответов и решений, спасибо в течение времени, которое Вы занимаете, чтобы записать им.

35
задан 26.06.2012, 20:57

3 ответа

Попытайтесь использовать xargs:

cat list.txt | xargs -J % cp % new_folder

Обновление:

Я сделал это на OS X, который имеет другую версию, чем версии GNU/Linux. xargs то, которое прибывает из GNU findutils, не имеет -J но это имеет -I который подобен (как Dennis Williamson, на которого указывают в комментарии). Версия OS X xargs имеет обоих -I и -J которые имеют немного отличающиеся поведения - любой будет работать на этот исходный вопрос.

$ cat list.txt
one
two.txt
three.rtf

$ cat list.txt | xargs -J % echo cp % new_folder
cp one two.txt three.rtf new_folder

$ cat list.txt | xargs -I % echo cp % new_folder
cp one new_folder
cp two.txt new_folder
cp three.rtf new_folder
34
ответ дан 07.12.2019, 08:59

Никакая потребность в cat вообще:

xargs -a list.txt cp -t new_folder

Или использование долгих опций:

xargs --arg-file=list.txt cp --target-directory=new_folder

Вот некоторые версии оболочки. Обратите внимание, что некоторые переменные закрываются кавычки или for циклы используются конкретно, потому что OP указал, что имена файлов являются разграниченным пространством. Некоторые из этих методов не будут работать на вход имени файла на строку, в котором имена файлов содержат пробел.

Bash:

for file in $(<list.txt); do cp "$file" new_folder; done

или

cp $(<list.txt) new_folder

sh (или Bash):

# still no cat!
while read -r line; do for file in $line; do cp "$file" new_folder; done; done < list.txt

или

# none here either
while read -r line; do cp $line new_folder; done < list.txt

или

# meow
for file in $(cat list.txt); do cp "$file" new_folder; done

или

# meow
cp $(cat list.txt) new_folder
54
ответ дан 07.12.2019, 08:59

У меня был смущающе окольный ответ здесь ранее, но ответ Denis напомнил мне, что я пропустил самую основную вещь. Так, я удалил свой исходный ответ. Но так как никто не сказал эту очень простую вещь, я думаю, что стоит поместить его здесь.

Исходный вопрос, "У меня есть текстовый файл со списком разделенных пробелом названий файлов. Как я могу скопировать тех, которые к одному целевому каталогу". Сначала это могло бы казаться хитрым или сложным, потому что Вы думаете, что необходимо так или иначе извлечь объекты из файла в особенном методе. Однако, когда оболочка обрабатывает командную строку, первая вещь, которую она делает, разделяют список аргументов на маркеры, и (вот бит, который никто не сказал напрямую), пробелы отдельные маркеры. (Новые строки также разделяют маркеры, который является, почему тест Doug Harris с новой строкой отделился, список имел тот же результат.) Таким образом, оболочка ожидает и может уже обработать разделенный пробелом список.

Таким образом, все, что необходимо сделать здесь, помещается разделенный пробелом список (что Вы уже имеете) в правильное место в Вашей команде. Ваша команда является некоторой вариацией на это:

cp file1 file2 file3...file# target

Единственная морщина - то, что Вы хотите получить список файлов 1 через # от Вашего текстового файла.

Как Dennis указывает в своем комментарии, Ваша исходная попытка (cpкошка list.txtnew_folder) уже должен был работать. Почему? Поскольку внутренняя команда cat list.txt обрабатывается сначала оболочкой и расширяется в file1 file2 file3...file#, который является точно, что оболочка ожидает и хочет в той части команды. Если это не работало затем ни один (1) у Вас была опечатка или (2) Ваши имена файлов были так или иначе странными (у них были пробелы или другие необычные символы).

Причина, что работа ответов всего Dennis состоит просто в том, что они предоставляют необходимый список файлов для cp продолжать работать, помещая тот список, где это принадлежит всей команды. Снова, сама команда - это в структуре:

cp list-of-files target_directory

Легко видеть, как это все объединяется в этой версии:

cp $(<list.txt) new_folder

$() заставляет оболочку выполнять команду в круглых скобках и затем заменять ее выводом в той точке в большей строке. Затем оболочка выполняет строку в целом. Между прочим, $() более современная версия того, что Вы уже делали с обратными галочками (').Далее: < оператор перенаправления файла. Это говорит оболочке выводить содержание list.txt к стандартному входу. Начиная с $() бит обрабатывается сначала, вот то, что происходит шаг за шагом:

  1. cp $(<list.txt) new_folder # split line into three tokens: cp, $(<list.txt), new_folder
  2. cp file1 file2 file3...file# new_folder # substitute result of $(<list.txt) into the larger command

Очевидно, шаг 2 является просто нормальным cp управляйте, чтобы Вы хотели.

Я понимаю, что побеждаю это (возможно, очень мертвый) лошадь много, но я думаю, что это стоит сделать. Понимание точно, как оболочка обрабатывает команду, может помочь Вам записать это лучше и упростить много. Это также покажет Вам, где проблемы, вероятно, будут скрываться. В этом случае, например, мой первый вопрос Вам должен был быть о забавных именах файлов или возможной опечатке. Никакая акробатика не была необходима.

7
ответ дан 07.12.2019, 08:59

Теги

Похожие вопросы