Разница между GNU find -not и GNU find -prune -o -print

Во-первых, не всегда верно, что стандартный ввод связан с клавиатурой. Во-вторых, вы не используете стандартный ввод для передачи чего-либо в echo. Вы используете клавиатуру для передачи строки echo fooв вашу оболочку. Оболочка анализирует эту строку и вызывает команду с именем echo(, независимо от того, является ли команда встроенной в оболочку или исполняемым файлом /usr/bin/echoили /bin/echoне имеет значения ), которая анализирует свои аргументы, игнорирует свой стандартный ввод и записывает строкаfoo\n

2
24.01.2021, 15:13
2 ответа

Во-первых, обратите внимание, что -notявляется расширением GNU и является эквивалентом стандартного оператора !. Он практически не имеет преимуществ перед !.

Предикат -pruneвсегда оценивается как true и влияет на то, как findпроходит по дереву каталогов. Если файл, для которого запускается -prune, имеет тип каталог (, возможно определенный после разрешения симлинков с помощью -L/-H/-follow), то findв него не спустится.

Таким образом,-name 'pattern' -prune(сокращение от-name 'pattern' -a -prune)такое же, как -name 'pattern', за исключением того, что каталоги, имя которых соответствует pattern, будут сокращены , то есть findне будут опускаться в них..

-name '.?*'соответствует файлам, имя которых начинается с ., за которым следует один символ (, определение которого зависит от текущей локали ), за которым следует 0 или более символов . Таким образом, это соответствует ., за которым следует один или несколько символов (, чтобы не обрезать .начальный каталог ).

Таким образом, это соответствует скрытым файлам с оговоркой, что оно соответствует только тем, имя которых также полностью состоит из символов , то есть является допустимым текстом в текущей локали (, по крайней мере, с реализацией GNU ).

Так вот,

find. \( -name '.?*' -a -prune \) -o -type f -a -print

То же, что и

find. -name '.?*' -prune -o -type f -print

поскольку И (-a, подразумеваемый )имеет приоритет над ИЛИ(-o).

находит файлы, которые являются обычными(без символической ссылки, каталога, fifo, устройства...)и не скрыты и не находятся в скрытых каталогах (при условии, что все пути к файлам являются допустимым текстом в локали ).

find. -type f -not -name '^.*'

Или его стандартный эквивалент:

find. -type f ! -name '^.*'

Будут найдены обычные файлы, имя которых не начинается с ^..

find. -type f ! -name '.*'

Найдет обычные файлы, имя которых не начинается с ., но по-прежнему будет сообщать о файлах в скрытых каталогах.

find. -type f ! -path '*/.*'

Пропустит скрытые файлы и файлы в скрытых каталогах, но findпо-прежнему будет спускаться в скрытые каталоги (любого уровня глубины )только для пропуска всех файлов в них, поэтому менее эффективен, чем подход с использованием -prune.

6
18.03.2021, 22:34

Предикат -pruneв findудаляет ветвь дерева поиска. Следовательно, использование -pruneв качестве первой команды в вашем вопросе даст вам те же результаты, что и ваша вторая команда, только если в каталогах нет файлов со скрытыми именами.

Пример:

$ tree -a
.
|--.hiddendir
|   `-- file
`-- dir
    `-- file

2 directories, 2 files
$ find. \( -name '.?*' -prune \) -o -type f -print
./dir/file
$ find. -type f ! -name '.*'
./dir/file
./.hiddendir/file

(Я исправил тест -nameздесь, поскольку вы, кажется, используете бессмысленное регулярное выражение, и я использовал !вместо нестандартного --not).

Как видите, поскольку имя .hiddendirсоответствует шаблону подстановки .?*, оно удаляется из дерева поиска с помощью первой команды, а файл fileпод ним не найден.

Во второй команде каталог .hiddendirне удаляется из дерева поиска, поэтому файл fileв нем найден.

5
18.03.2021, 22:34

Теги

Похожие вопросы