Я пытаюсь запустить команду, похожую на приведенную ниже, в скрипте bash. Он должен искать во всех подпапках $sourcedir
и копировать все файлы определенного типа на корневой уровень $targetdir
.
#!/bin/bash
# These are set as arguments to the script, not hard-coded
sourcedir="/path/to/sourcedir"
targetdir="/path/to/targetdir"
find "$sourcedir" -type f -name "*.type" -exec sh -c 'cp "$1" "$2/`basename "$1"`"' "{}" "$targetdir" \;
Это, кажется, довольно близко, за исключением того, что {}
не передается в $2
отношении-exec sh -c ...
Я хотел бы сделать это как можно ближе к «правильному пути», с допуском для специальных символов в именах файлов (особенно символы одинарных кавычек).
Изменить: я вижу людей, предлагающих использовать xargs
или цепочки аргументов. У меня сложилось впечатление, что это нормально только для ограниченного числа аргументов. Если у меня есть, например, тысячи файлов .jpg, которые я пытаюсь скопировать из нескольких каталогов галерей в гигантский каталог слайд-шоу, будут ли работать решения, объединяющие аргументы?
Изменить 2: Моя проблема заключалась в том, что я пропустил _
перед моей первой опцией sh в -exec
команде. Для тех, кому интересно, как заставить команду find работать, добавьте _
и все будет хорошо:
find "$sourcedir" -type f -name "*.type" -exec sh -c 'cp "$1" "$2"' _ "{}" "$targetdir" \;
Я принял ответ ниже, потому что он выполняет ту же задачу, но более эффективен и элегантен.
источник
xargs
был создан, чтобы автоматически обрабатывать огромное количество аргументов в обычных командах, имеющих ограничения. Также следует учитывать, что большинство пределов максимального аргумента были значительно улучшены для стандартных утилит GNU. Вы также увидите выигрыш в производительности, избегая всех тех разветвлений процессов, которые важны для тысяч файлов.Ответы:
Вы хотите скопировать файлы определенного типа в определенный каталог? Лучше всего это сделать
xargs
, а вам это даже не нужноsh
. Это более подходящий способ сделать это, должен также работать более эффективно.Если вам нужно обрабатывать специальные имена файлов, используйте их
NULL
как разделительисточник
-print0
вfind
и-0
кxargs
NULL
нет необходимости, если вы используете'{}'
, важно, когда вы не используете. Реальная выгода между одним из других, помимоPOSIX
соблюдения, является производительность.Вам нужно передать
{}
в качестве аргумента оболочку, а затем выполнить цикл по каждому аргументу.Примечание : способ, которым это работает, заключается в том, что первым аргументом для оболочки является имя оболочки , мы можем использовать это, передавая имя как
$targetdir
и затем используя специальный параметр$0
внутри сценария оболочки для доступа к этому targettdir.источник
"$targetdir"
не раскрывается внутри одинарных кавычек.Если вы не верите в церковь Xargs:
Объяснение:
копирует b, c и d в целевой каталог a.
вызывает команду для большого количества файлов сразу, а не один за другим (что является стандартным, если вы используете
";"
вместо+
). Вот почему вы должны вытащить targettdir вперед и отметить его как цель.Это работает для gnu-find и может не работать для других реализаций find. Конечно, это также зависит от -t -flag.
TechZilla, конечно, так далеко, так как
sh
не нужен для вызова cp.Если вы не используете
xargs
, что большая часть времени ненужного в сочетании сfind
, вы спасены от обучения-print0
и-0
флага.источник
xargs
. Самый большой пример, что делать, если вы не находите файлы? Я все время использую xargs вместо общихfor
циклов,find
гораздо меньше по объему. Кроме того,find
поддерживается только то, что+
если вы используете GNUfind
, это не определено в POSIX. Так что, хотя вы не стесняйтесь предпочитать вfind
одиночку, он делает не все, что делает xargs Когда вы рассматриваете GNU,xargs
вы также получаете-P
многоядерный процессор. Это стоит учитьсяxargs
независимо.источник