Каким образом параметры цитирования «находят»?

При поиске txt-файлов я запускаю эту команду:

find . -name "*.txt" -print 

Это дает мне список всех текстовых файлов под текущей директорией.

Однако find . -name *.txt -print find . -name *.txt -print дает мне следующую ошибку: find: paths must precede expression: mein.txt

Это общепринятое поведение? Какая разница в кавычках?

Внутри токена, который не указан, ваша оболочка будет выполнять расширение, а не команду, которую вы выполняете.

Это означает, что когда вы входите в find . -name "*.txt" -print find . -name "*.txt" -print , то find получает литерал *.txt качестве одного из его параметров и использует этот шаблон в качестве аргумента для параметра -name , который будет соответствовать именам файлов, найденных против него перед применением -print .

С другой стороны, когда вы входите в find . -name *.txt -print find . -name *.txt -print , оболочка передает расширенную версию *.txt для поиска. Возможны несколько случаев:

  1. Нет файлов, соответствующих *.txt в текущем каталоге: find получает литерал *.txt (при условии установки bash по умолчанию);

  2. в текущем каталоге есть ровно один файл, соответствующий *.txt ; скажем, это a.txt : find получает это имя файла и соответствует всем файлам с именем a.txt найденным начиная с текущего каталога;

  3. несколько файлов соответствуют *.txt в текущем каталоге (это, по-видимому, ваш случай): -name принимает первый в качестве своего параметра, а остальные – дополнительные параметры пути для поиска, которые жалуются на то, что не заданы все пути до выражения ,

Это ожидаемое поведение.


Предположим следующую иерархию файлов:

 . ├── a.txt ├── b.txt ├── c.txt └── foo ├── a.txt ├── b.txt └── c.txt 

Фактические параметры, которые находят полученные в случае eah, можно наблюдать, заменив вызов на поиск с помощью printf '%s\n' , который будет печатать каждый расширенный аргумент в своей строке:

 $ printf '%s\n' . -name "*.txt" -print . -name *.txt -print $ printf '%s\n' . -name *.txt -print . -name a.txt b.txt c.txt -print 

Как вы можете видеть, второе сообщение, которое вы отправили, эквивалентно, учитывая существующие файлы, чтобы find . -name a.txt b.txt c.txt -print find . -name a.txt b.txt c.txt -print .

Это ожидаемое поведение – это называется «shell globbing». Без кавычек *.txt оболочкой, чтобы передать весь список файлов, соответствующих этому выражению, команде find . Окружая его в кавычках, вы сообщаете оболочке передать литеральную строку *.txt для find . Вы можете добиться такой же защиты, используя другие методы экранирования, такие как find . -name \*.txt find . -name \*.txt или find . -name '*.txt' find . -name '*.txt' .