У Общества Наследия Unix есть загрузка старого Подлинного исходного кода Unix. Страница исходного кода имеет Unix Bell Labs от Версии 1 - 6, 32V, Система III, некоторые или все BSDs, указатели на прародителя Linux Minix.
Самый безопасный путь состоит в том, чтобы использовать globbing:
for file in *pdf; do echo pathname "$file"; done
Если необходимо найти весь PDF рекурсивно, сделайте это:
shopt -s globstar
for file in **/*pdf; do echo pathname "$file"; done
Как сказано многие время на этом сайте, оставляя переменное расширение (как в $var
) или замена команды (как в `cmd`
или $(cmd)
) (или арифметическое расширение (как в $((11 * 11))
) в большинстве оболочек), закрыл кавычки в оболочках Границы/POSIX, split+glob оператор.
Содержание $var
или вывод cmd
(без запаздывающих символов новой строки), разделяется согласно текущему значению $IFS
специальная переменная (который по умолчанию содержит SPC, ВКЛАДКУ и символы NL (и NUL в zsh
)) и каждое слово, получающееся из того разделения, подвергается поколению имени файла, также известному как globbing.
Например, если find
ouputs ./foo bar.pdf\n./*foo*\tbar.pdf\n
(\t
значение ВКЛАДКИ и \n
NL), со значением по умолчанию $IFS
, замена команды расширится до ./foo bar.pdf\n./*foo*\tbar.pdf
(запаздывание удаленной новой строки), и затем быть разделенным на ./foo
, bar.pdf
, ./*foo*
, и foo.pdf
и ./*foo*
то, которое является подстановочным шаблоном, будет расширено в столько же аргументов, сколько существуют нескрытые файлы в текущем каталоге, имя которого содержит foo
.
Если Вы хотите разделить на символах новой строки только, необходимо установить $IFS
к новой строке только:
IFS='
'
Если Вы не хотите, чтобы подстановочные шаблоны были расширены, необходимо отключить его с
set -f
Однако обратите внимание, что новая строка является столь же допустимым символом как любой в имени файла, так в более общем плане, find -print
вывод не может быть выполнен последующую обработку надежно.
Вывод как:
./a.pdf
./b.pdf
любое средство a.pdf
и b.pdf
файлы в текущем каталоге или названный файл b.pdf
в a.pdf\n.
каталог.
Некоторые find
реализации как GNU find
(где это произошло из), имеют a -print0
предикат для вывода имени файла, сопровождаемого символом NUL вместо символа NL. Со стандартом find
, можно использовать -exec printf '%s\0' {} +
с тем же результатом. NUL является единственным символом, который не может произойти в имени файла.
Однако zsh
единственная оболочка, которая может сохранить символ NUL в его переменных (как $IFS
символ), таким образом:
IFS=$'\0'
for i in `find ... -print0`; do
...
done
(никакая потребность в set -f
в zsh
с тех пор zsh
не делает globbing на замену команды), будет работать в zsh
но не в других оболочках.
Лучше всего, и портативно, должен иметь find
назовите команды, Вы хотите работать на тех файлах. Поскольку @Gnouc предлагает:
find . -name '*.pdf' -exec the command {} \;
При необходимости в чем-нибудь более сложные операторы оболочки вовлечения можно все еще сделать вещи как:
find . -name '*.pdf' -exec sh -c '
for i do
something complex with "$i"
done' sh {} +
С zsh
или bash
, можно также сделать:
find . -name '*.pdf' -print0 |
while IFS= read -r -d '' file; do
whatever with "$file"
done
Однако обратите внимание, что stdin в цикле затронут.
zsh
(с 1990) имеет большую часть функциональности find
включенный в его globbing возможности через синтаксис, где можно указать любой уровень подкаталогов ((*/)#
синтаксис или его более простая форма **/
) и спецификаторы globbing (которые являются кулоном -type f
, -mtime
, -perm
... в find
).
**/
часть этого была скопирована ksh93
в 2003, fish
в 2005, bash
в 2009 и tcsh
в 2010 (хотя tcsh
также скопированный ***/
часть). И все они не включают его по умолчанию. К сожалению, отметьте это оба bash
и fish
**
действительно следуйте за символьными ссылками на каталоги (как -L
/-follow
в find
, или ***
в zsh
или tcsh
).
В тех оболочках можно найти pdf
файлы на любом уровне подкаталогов, не имея необходимость полагаться find
, но отметьте тот протест выше о fish
и bash
, и только zsh
имеет globbing спецификаторы.
Так, например, zsh
эквивалентный из:
find . -name '*.pdf' -type f -exec ls -ld {} +
был бы:
ls -ld ./**/*.pdf(D.)
В то время как с bash
, необходимо было бы сделать что-то как:
shopt -s failglob
shopt -s globstar
files=(./**/*.pdf) &&
for i do
[ -f "$i" ] && ! [ -L "$i" ] && set -- "$i" "$@"
shift
done && ls -ld "$@"
Существует несколько опций. Придерживаясь решения для цикличного выполнения, можно использовать read
считать строку за один раз в переменную:
find . -name "*.pdf" | while IFS= read -r x
do
echo pathname "$x"
done
Можно также использовать xargs -0
и find -print0
обработать любой вид специальных символов:
find . -name "*.pdf" -print0 | xargs -0 -L1 echo pathname
Попробуйте это в остроте:
find ./ -name "*.pdf" -exec echo pathname {} \;
find
будет заботиться о цикличном выполнении (использующий циклы в оболочке, обычно плохая практика), и назовет любую команду, которую Вы хотите, чтобы это выполнило, сюда echo
как в вопросе OP. Предоставленный, echo
плохой выбор команд, но это - команда, которую использовал OP.
– Stéphane Chazelas
13.06.2013, 22:12
echo pathname $foo
. Это решение идентично тому, что делает OP, и его вывод все еще не может быть сохранен в переменной.
– terdon♦
13.06.2013, 22:18
-exec
но Вы все еще не можете использовать это для сохранения find
вывод в переменной. Предоставил, хочет ли весь OP, должен распечатать строку pathname
перед фактическим путем затем это - все, в чем Вы нуждаетесь. Но не, если намерение более сложно, чем какой -exec
может обработать. И да, я знаю что {}
:).
– terdon♦
13.06.2013, 22:22
После поиска решения для оболочки FreeBSD по умолчанию (/bin/sh), В конце концов я придумал свое собственное решение. Это включает в себя использование sed для уничтожения / создания пробелов. Это также позволит вам изменять переменные в вашем цикле и использовать их внешне, в отличие от использования цикла while (в то время как петли порождают подоболочки в /bin/sh).
REMOTE_FOLDER=/media/images
FILE_LIST=$(find $REMOTE_FOLDER | sed 's/ /\/\/\/\//g')
for FILE in $FILE_LIST; do
FILE=$(echo $FILE | sed 's/\/\/\/\// /g')
# do whatever you need to do with $FILE
done
bash
**/
следует за символьными ссылками при убывании дерева каталогов, которое обычно является не, что Вы хотите, можно хотеть использоватьksh93
один (которыйbash
скопированный это с и не имеет проблемы), или еще лучшеzsh
один (которыйksh93
скопированный это с), где у Вас может быть большая часть функциональностиfind
через его globbing спецификаторы. – Stéphane Chazelas 13.06.2013, 22:14