find
와일드카드로 제한되어 있지만 경로 이름에 공백이 있는 폴더 집합에서 파일을 찾는 데 사용하고 싶습니다 .
명령줄에서는 쉽습니다. 다음 예제는 모두 작동합니다.
find te*/my\ files/more -print
find te*/'my files'/more -print
find te*/my' 'files/more -print
terminal/my files/more
예를 들어 및 에서 파일을 찾습니다 tepid/my files/more
.
그러나 이것이 스크립트의 일부가 되어야 합니다. 내가 필요한 것은 다음과 같습니다.
SEARCH='te*/my\ files/more'
find ${SEARCH} -print
find
불행하게도 내가 무엇을 하든 스크립트 내의 명령 에 와일드카드와 공백을 혼합할 수 없는 것 같습니다 . 위의 예는 다음 오류를 반환합니다(예기치 않게 백슬래시가 두 배로 늘어난 것에 주의하세요).
find: ‘te*/my\\’: No such file or directory
find: ‘files/more’: No such file or directory
따옴표를 사용하려고 해도 실패합니다.
SEARCH="te*/'my files'/more"
find ${SEARCH} -print
따옴표의 의미를 무시하고 다음 오류를 반환합니다.
find: ‘te*/'my’: No such file or directory
find: ‘files'/more’: No such file or directory
여기에 또 하나의 예가 있습니다.
SEARCH='te*/my files/more'
find ${SEARCH} -print
예상대로:
find: ‘te*/my’: No such file or directory
find: ‘files/more’: No such file or directory
내가 시도한 모든 변형은 오류를 반환합니다.
너무 많은 폴더를 반환하기 때문에 잠재적으로 위험할 수 있는 해결 방법이 있습니다. 다음과 같이 모든 공백을 물음표(단일 문자 와일드카드)로 변환합니다.
SEARCH='te*/my files/more'
SEARCH=${SEARCH// /?} # Convert every space to a question mark.
find ${SEARCH} -print
이는 다음과 같습니다.
find te*/my?files/more -print
이는 올바른 폴더뿐만 아니라 terse/myxfiles/more
예상되지 않은 을 반환합니다.
내가 하려는 일을 어떻게 성취할 수 있나요? Google은 나에게 도움이 되지 않았습니다 :(
답변1
정확히 동일한 명령이 스크립트에서 제대로 작동해야 합니다.
#!/usr/bin/env bash
find te*/my\ files/ -print
만약 너라면필요변수로 사용하려면 좀 더 복잡해집니다.
#!/usr/bin/env bash
search='te*/my\ files/'
eval find "$search" -print
경고:
이와 같이 사용하는 것은 eval
안전하지 않으며 파일 이름에 특정 문자가 포함될 수 있는 경우 임의적이고 유해한 코드가 실행될 수 있습니다. 보다배쉬 FAQ 48자세한 내용은.
경로를 인수로 전달하는 것이 더 좋습니다.
#!/usr/bin/env bash
find "$@" -name "file*"
find
또 다른 접근 방식은 bash의 확장된 글로빙 기능과 글롭을 완전히 피하고 사용하는 것입니다 .
#!/usr/bin/env bash
shopt -s globstar
for file in te*/my\ files/**; do echo "$file"; done
bash globstar
옵션을 사용하면 재귀적으로 일치하는 데 사용할 수 있습니다 **
.
globstar
If set, the pattern ** used in a pathname expansion con‐
text will match all files and zero or more directories
and subdirectories. If the pattern is followed by a /,
only directories and subdirectories match.
도트 파일(숨겨진 파일)을 찾아 포함하는 것처럼 100% 작동하게 하려면 다음을 사용하세요.
#!/usr/bin/env bash
shopt -s globstar
shopt -s dotglob
for file in te*/my\ files/**; do echo "$file"; done
echo
루프 없이 직접 만들 수도 있습니다 .
echo te*/my\ files/**
답변2
배열은 어떻습니까?
$ tree Desktop/ Documents/
Desktop/
└── my folder
└── more
└── file
Documents/
└── my folder
├── folder
└── more
5 directories, 1 file
$ SEARCH=(D*/my\ folder)
$ find "${SEARCH[@]}"
Desktop/my folder
Desktop/my folder/more
Desktop/my folder/more/file
Documents/my folder
Documents/my folder/more
Documents/my folder/folder
(*)
와일드카드와 일치하는 모든 배열로 확장됩니다. 그리고 각각 개별적으로 인용된 "${SEARCH[@]}"
배열( )의 모든 요소로 확장됩니다 .[@]
뒤늦게야 발견 자체가 이런 일을 할 수 있다는 것을 깨달았습니다. 다음과 같은 것 :
find . -path 'D*/my folder/more/'
답변3
지금은 약간 구식이지만 이 질문에 대해 누구에게나 도움이 될 수 있다면 find 명령줄 인수 내에서 변수를 [[.space.]]
인용하지 않고 RE의 조합 기호를 사용하는 $SEARCH
것은 별표 대신 확장된 경로 이름에 특수 문자가 없는 한 작동하는 것입니다.
set -x
mkdir -p te{flon,nnis,rrine}/my\ files/more
SEARCH=te*/my[[.space.]]files/more
find $SEARCH
다음 결과를 제공합니다.
+ mkdir -p 'teflon/my files/more' 'tennis/my files/more' 'terrine/my files/more'
+ SEARCH='te*/my[[.space.]]files/more'
+ find 'teflon/my files/more' 'tennis/my files/more' 'terrine/my files/more'
teflon/my files/more
tennis/my files/more
terrine/my files/more
원하지 않는 문자를 글로빙하는 것을 방지하기 위해 별표( *
)를 조합 요소(문자)로 바꿀 수 있습니다.
set -x
mkdir -p -- te{,-,_}{flon,nnis,rrine}/my\ files/more
SEARCH=te[[:alnum:][.space.][.hyphen.][.underscore.]]*/my[[.space.]]files/more
find $SEARCH
다음과 같은 결과를 제공합니다.
+ mkdir -p -- 'teflon/my files/more' 'tennis/my files/more' 'terrine/my files/more' \
'te-flon/my files/more' 'te-nnis/my files/more' 'te-rrine/my files/more' \
'te_flon/my files/more' 'te_nnis/my files/more' 'te_rrine/my files/more'
+ SEARCH='te[[:alnum:][.space.][.hyphen.][.underscore.]]*/my[[.space.]]files/more'
+ find 'te-flon/my files/more' 'te_flon/my files/more' 'teflon/my files/more' \
'te-nnis/my files/more' 'te_nnis/my files/more' 'tennis/my files/more' \
'te-rrine/my files/more' 'te_rrine/my files/more' 'terrine/my files/more'
te-flon/my files/more
te_flon/my files/more
teflon/my files/more
te-nnis/my files/more
te_nnis/my files/more
tennis/my files/more
te-rrine/my files/more
te_rrine/my files/more
terrine/my files/more
줄을 줄이려면 을 또는 [.hyphen.]
로 바꿀 수 있고 또는 로 바꿀 수 있습니다 .[.-.]
-
[.underscore.]
[._.]
_
\
가독성을 위해 직접 추가한 백슬래시( )를 사용하여 줄을 자릅니다 .
답변4
드디어 답을 알아냈습니다.
모든 공백에 백슬래시를 추가합니다.
SEARCH='te*/my files/more'
SEARCH=${SEARCH// /\\ }
이 시점 SEARCH
에서 te*/my\ files/more
.
그런 다음 eval
.
eval find ${SEARCH} -print
그것은 간단합니다! 를 사용하면 변수의 eval
해석이 무시됩니다 .${SEARCH}