1

Привет, это может быть очень новый вопрос, но почему в этом случае xargs /bin /ls не работает? Я думал, что это должно было быть быстрее? И что это за каталоги /fd /3?

sh-3.2# find / -name 'GOALS*' -exec ls -l {} \;
find: /dev/fd/3: Not a directory
find: /dev/fd/4: Not a directory
.... This returns me the expected result....

Однако это возвращает весь список файлов в каталоге

sh-3.2# find / -name GOALS* -type f | xargs /bin/ls -l

Я на MacOS.

3 ответа3

1
  1. вам нужно указать * во второй команде find ,

  2. /dev/fd/* - это устройства, которые соответствуют stdin , stdout , stderr и т. д. Эти устройства связаны друг с другом и различаются для каждого процесса,

  3. -type f говорит, что результат должен быть обычным файлом, поэтому /dev/fd/* нет в результате, поскольку они являются блочными устройствами,

  4. xargs ls -l делает то же самое, что и ваш ls -l {} ... Я даже сомневаюсь в лучшем быстродействии в этом случае, но xargs умнее и есть причины использовать его, например. правильная обработка файлов с пробелами внутри,

Если вы отлаживаете вторую версию вашей find , прежде всего посмотрите вывод без | xargs ls -l part

1

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

Вторая команда сопоставляет только файл с указанным именем. Поскольку вы не указали GOALS* , если вы запускаете из каталога с соответствующей записью, он заменит запись GOALS* в команде. xargs вызывает ls длинный список имен файлов. Вы не увидите результатов, пока не завершится поиск или не будет найден достаточно длинный список совпадений. Из-за правил синтаксического анализа имя файла, которое содержит пробелы, вызовет проблемы.

Эти три команды должны быть эквивалентны для файлов без пробелов в имени. Третий вариант работает не во всех операционных системах, но обрабатывает пробелы в имени.

find / -name 'GOALS*' -type f -exec ls -l {} \;
find / -name 'GOALS*' -type f | xargs /bin/ls -l
find / -name 'GOALS*' -type f -print0 | xargs -0 /bin/ls -l
0

Встроенная в exec оболочка (bash) заменяет текущую оболочку с заданным аргументом. Попробуйте exec sleep 1, например. Исполняемый файл xargs является частью пакета GNU findutils. Он выполнит команду, данную ему как первый аргумент с аргументом, считанным из стандартного ввода.

Например:

$ echo -e "calves drink milk\npeople eat cows" | xargs -L1 cowsay
 ___________________
< calves drink milk >
 -------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
 _________________
< people eat cows >
 -----------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Приведенный вами пример "не работает", потому что список аргументов, состоящий из всех файлов на вашем компьютере и специальных файлов в /sys и /proc, становится слишком большим. Вы не можете попросить команду работать с произвольно большим списком аргументов, потому что есть предел (getconf ARG_MAX - я думаю, байты).

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

Например:

$ cat tmp/moo.sh
#!/bin/sh
echo processing $# arguments

$ seq 0 10000 | xargs -L 1001 sh tmp/moo.sh  | cat -n
     1  processing 1001 arguments
     2  processing 1001 arguments
     3  processing 1001 arguments
     4  processing 1001 arguments
     5  processing 1001 arguments
     6  processing 1001 arguments
     7  processing 1001 arguments
     8  processing 1001 arguments
     9  processing 1001 arguments
    10  processing 992 arguments

В последней части вашего вопроса о папках "тех Fd" о F Ile д escriptors. Когда вы запускаете find, он просматривает /proc и видит файловые дескрипторы (стандартный ввод, стандартный вывод, обычные файлы для чтения и записи) запущенных процессов. К тому времени, когда команды find выходят и xargs вступают во владение, некоторые из этих процессов могут уже не существовать. Таким образом, ошибки. Файлы в /dev /fd на самом деле являются только символическими ссылками:

$ ll /dev/fd/
total 0
lrwx------ 1 jaroslav jaroslav 64 Nov 18 01:57 0 -> /dev/pts/7
lrwx------ 1 jaroslav jaroslav 64 Nov 18 01:57 1 -> /dev/pts/7
lrwx------ 1 jaroslav jaroslav 64 Nov 18 01:57 2 -> /dev/pts/7
lr-x------ 1 jaroslav jaroslav 64 Nov 18 01:57 3 -> /proc/21677/fd
geee: ~
$ file /dev/pts/7
/dev/pts/7: character special
geee: ~
$ sudo echo "MOOOOOOO" >>  /dev/pts/7
Password:
MOOOOOOO

То, что я там сделал, я написал в стандартный вывод моего терминала. Я понятия не имею, что представляет собой процесс 21677, но к тому времени, когда find / завершение, я уверен, что он будет уничтожен, даже если он присутствовал во время поиска отсканированного /proc.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .