Раніше тут я мав бентежну відповідь, але відповідь Дениса нагадала мені, що я пропустив найосновніше. Отже, я видалив свою оригінальну відповідь. Але оскільки ніхто не сказав цього дуже елементарного, я вважаю, що варто це поставити тут.
Оригінальне запитання - "У мене є текстовий файл із переліком розділених пробілами імен файлів. Як їх скопіювати в один цільовий каталог". Спочатку це може здатися хитромудрим або складним, оскільки ви думаєте, що вам потрібно якось певним чином витягти елементи з файлу. Однак, коли оболонка обробляє командний рядок, перше, що вона робить, - це розділити список аргументів на маркери і (ось біт, який ніхто не сказав прямо), пробіли окремі лексеми . (Newlines також окремі лексеми, тому тест Дуга Харріса з новим розділеним списком мав той же результат.) Тобто оболонка очікує і вже може обробляти список, розділений пробілом.
Отже, все, що вам потрібно зробити тут, - поставити розділений пробілом список (який у вас уже є) на потрібне місце у вашій команді. Ваша команда щодо цього є різною:
cp file1 file2 file3...file# target
Єдина зморшка полягає в тому, що ви хочете отримати список файлів від 1 до # з вашого текстового файлу.
Як зазначає Денніс у своєму коментарі, ваша оригінальна спроба ( cp
cat list.txt new_folder
) мала вже працювати. Чому? Оскільки внутрішня команда cat list.txt
опрацьовується спочатку оболонкою і розширюється в неї file1 file2 file3...file#
, саме це оболонка очікує і хоче в цій частині команди. Якщо це не спрацювало, то або (1) у вас був помилка друку, або (2) ваші імена були якось дивними (у них були пробіли чи інші незвичайні символи).
Причина того, що всі відповіді Денніса працюють просто в тому, що вони надають необхідний список файлів для cp
роботи, розміщуючи цей список там, де він належить всій команді. Знову ж таки, сама команда така за структурою:
cp list-of-files target_directory
Неважко зрозуміти, як це все поєднується в цій версії:
cp $(<list.txt) new_folder
$()
змушує оболонку запускати команду всередині круглих дужок, а потім підміняти її вихід у цій точці у більшому рядку. Потім оболонка запускає лінію в цілому. До речі, $()
це більш сучасна версія того, що ви вже робили з backticks (`). Далі: <
оператор перенаправлення файлів. Він повідомляє оболонці скинути вміст 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
команда, яку ви хотіли.
Я усвідомлюю, що я дуже б'ю цього (можливо, дуже мертвого) коня, але думаю, що варто це зробити. Розуміння того , як оболонка обробляє команду, може допомогти вам краще її написати та спростити багато. Він також покаже, де проблеми, ймовірно, ховаються. У цьому випадку, наприклад, моє перше запитання до вас мало стосуватись смішних імен або можливої помилки. Жодні акробатики не потрібні були.