#bash #command #cp
#bash #команда #cp
Вопрос:
Структура выглядит следующим образом
james /
hey / foo1 / foo2 / foo3
При вводе этой команды
cp hey foo*
Я получаю следующее уведомление
cp: пропуск каталога ‘foo1’
cp: пропуск каталога ‘foo2’
И файл hey копируется в каталог foo3.
Почему это происходит так? Почему hey был скопирован в каталог foo3, почему не в foo1 и foo2 ?
Комментарии:
1. Чего бы вы ожидали от этого? Поместите копию
hey
в каждое из имен каталогов, начинающихся сfoo
?2. Если это то, что вы хотите :
for d in foo*/; do cp -- hey "$d"; done
. Поскольку существует только один аргумент назначения для каждого вызоваcp
(проверьте справочную страницу!), Вам нужен один вызов для каждого назначения.3. Да, я хочу скопировать hey в каталоги foo со всеми суффиксами. Спасибо за ваш комментарий, теперь я получил свой ответ.
Ответ №1:
когда вы делаете это:
cp hey foo*
bash расширяет аргументы. В вашем случае командная строка расширяется до
cp hey foo1 foo2 foo3
Последний аргумент — целевой файл / каталог. cp
отказывается копировать каталоги, если -R/-r
опция не установлена, отсюда и сообщения.
И hey
файл копируется в foo3
cp
или любая другая команда не может определить разницу между командной строкой с *
и командной строкой с расширенными аргументами, в отличие от Windows cmd, например.
Если вам удастся передать фактический *
символ в cp
(например: cp foo* bar
), то cp
будет проверен вызываемый файл foo*
. В командах нет расширения механизма подстановочных знаков (некоторые есть в портах Windows, но это уже другая история)
Примечание: это не тот способ, которым его следует использовать:
- Если вы знаете, что есть только каталог с
foo
префиксом, это может быть способом копирования файлов в нем, не зная точного имени каталога. - более классическое использование:
cp *.txt foo
Примечание2: опасный случай: если у вас есть file1
и file2
и вы хотите скопировать их foo
, и вы вводите cp file*
, пропуская foo
(или нажимая RETURN по ошибке), он будет скопирован file1
file2
(в оболочках, которые не разворачивают подстановочные знаки, чего не может быть).
В вашем случае, если вы хотите скопировать hey
во все foo*
каталоги, вам нужно выполнить цикл:
for target in foo*
do
cp hey "$target"
done
Комментарии:
1. Возможно, стоит вызвать (хотя это уже подразумевается в вашем ответе), который
cp
не может определить, какой расширенный аргумент был получен из какой части исходной командной строки, поскольку он не может сообщить, что какая-либо «исходная командная строка» даже существовала.2. @CharlesDuffy я намекнул на это в своей второй заметке. Вы правы, я отредактирую.
3. кивок . Как я прочитал, OP хочет поместить одну копию
hey
в каждый изfoo*
каталогов, т. Е.. чтобы все они рассматривались как пункты назначения. Вы объясняете, почему это не работает, но несколько косвенно.4. @CharlesDuffy: Типичная проблема XY, верно? 🙂 Я добавил способ сделать это в конце моего ответа. Наконец, лучше попытаться исчерпывающе объяснить эту классическую проблему.
5. @CharlesDuffy: спасибо за редактирование! Я, очевидно, не тестировал это!