3

Я искал различия в команде find с двойными и без кавычек.

Я нашел что-то странное. У меня есть два файла:

  • xWrapper.java
  • YWrapper.java

и некоторые в шаблоне *Wrapper.java .

Я побежал

find . -name *Wrapper.java

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

find . -name xWrapper.java yWrapper.java ..

Но в результате я получил все файлы этой формы. Почему он возвращает все файлы, соответствующие этому шаблону?

3 ответа3

7

Во всяком случае, вы должны получить сообщение об ошибке, если вы находитесь в том же каталоге:

~$ mkdir test
~$ cd test
~/test$ touch {X,Y}Wrapper.java
~/test$ find . -name *Wrapper.java
find: paths must precede expression: YWrapper.java
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

поскольку звездочка будет развернута, а -name принимает только один аргумент.

Если вы пришли из места, где звездочка не развернута:

~/test$ cd ..
~$ find test -name *Wrapper.java
test/XWrapper.java
test/YWrapper.java

Поскольку звездочка теперь не раскрывается (если она не совпадает с чем-либо в текущем каталоге), find видит ее "как есть" и использует ее в качестве подстановочного знака.

Вы должны заключить аргумент -name в одинарные кавычки, чтобы избежать такого зависимого от контекста поведения:

~/test$ find . -name '*Wrapper.java'
./XWrapper.java
./YWrapper.java
0
[max@localhost ~]$ touch 1file
[max@localhost ~]$ touch 2file
[max@localhost ~]$ touch 3file
[max@localhost ~]$ touch 4file
[max@localhost ~]$ touch 5file
[max@localhost ~]$ find -name "*file"
./4file
./2file
./Desktop/new file
./Desktop/DESKTOP/new file
./.bash_profile
./#file
./3file
./1file
./5file
./file
./file/file

Это будет соответствовать всем именам файлов, оканчивающимся на file

[max@localhost ~]$ find . -name 'file*'
./file1
./.gconf/apps/file-roller
./Downloads/opera-10.60-6386.i386.linux/share/opera/unite/fileSharing.ua
./Downloads/opera-10.60-6386.i386.linux/share/opera/defaults/filehandler.ini
./Downloads/opera-10.60-6386.i386.linux/share/opera/styles/images/file.png
./.gnome2/file-roller
./.local/share/Trash/files
./file
./file/file2
./file/file

Это будет соответствовать все имя файла, начиная с file

[max@localhost ~]$ find -name "1file"
./1file

Это будет соответствовать только имени файла 1file

[max@localhost ~/avi]$ touch a
[max@localhost ~/avi]$ touch b
[max@localhost ~/avi]$ touch "a b"
[max@localhost ~/avi]$ ll
total 0
-rw-rw-r-- 1 max max 0 Jul 31 13:49 a
-rw-rw-r-- 1 max max 0 Jul 31 13:49 a b
-rw-rw-r-- 1 max max 0 Jul 31 13:49 b
[max@localhost ~/avi]$ find . -name a
./a
[max@localhost ~/avi]$ find . -name b
./b
[max@localhost ~/avi]$ find . -name a b
find: paths must precede expression: b
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] 
[expression]
[max@localhost ~/avi]$ find . -name "a b"
./a b

Символ ("или") будет полезен, когда между именами файлов есть пробел, например "a b"

0

Вы можете использовать функцию or потому что -name является аргументом из одной строки.

find . \( -name "xWrapper.java" -o -name "yWrapper.java" \)

Или вы можете использовать регулярное выражение, чтобы найти файл с

find . -regex '.*\(x\|y\)Wrapper.java'

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