Bash에서 글로벌에 일치하는 항목이 있는지 테스트
단일 파일이 있는지 확인하려면 다음을 사용하여 테스트할 수 있습니다.test -e filename
또는[ -e filename ]
.
만약 내가 글로벌을 가지고 있고 이름이 글로벌과 일치하는 파일이 있는지 알고 싶습니다.글로벌은 0개의 파일(이 경우 아무것도 할 필요가 없음)과 일치하거나 1개 이상의 파일(이 경우 무언가를 수행해야 함)과 일치할 수 있습니다. 글로벌에할 수 있을까요? (몇 항목이, 한 의 일치 항목으로 할 수 것입니다.)if
문장과 루프가 없습니다(단순히 읽을 수 있기 때문입니다).
(test -e glob*
글로벌이 둘 이상의 파일과 일치하는 경우 실패합니다.)
Bash 관련 솔루션:
compgen -G "<glob-pattern>"
패턴을 피하지 않으면 일치 항목으로 미리 확장됩니다.
종료 상태:
- 1: 일치하지 않는 경우,
- '하나 이상의 일치'의 경우 0
stdout
글로벌과 일치하는 파일 목록입니다.저는 이것이 간결함과 잠재적인 부작용을 최소화하는 측면에서 가장 좋은 선택이라고 생각합니다.
예:
if compgen -G "/tmp/someFiles*" > /dev/null; then
echo "Some files exist."
fi
nullglob 쉘 옵션은 실제로 배시즘입니다.
nullglobal 상태의 지루한 저장 및 복원이 필요하지 않도록 Global을 확장하는 하위 셸 내에서만 설정합니다.
if test -n "$(shopt -s nullglob; echo glob*)"
then
echo found
else
echo not found
fi
휴대성을 향상시키고 보다 유연한 글러브링을 위해 다음 찾기를 사용합니다.
if test -n "$(find . -maxdepth 1 -name 'glob*' -print -quit)"
then
echo found
else
echo not found
fi
검색 기준과 일치하는 첫 번째 파일을 찾는 즉시 찾기가 종료되도록 기본 암묵적 -print 작업 대신 명시적 -print -quit 작업이 검색에 사용됩니다.많은 파일이 일치하는 경우 이는 다음보다 훨씬 더 빨리 실행되어야 합니다.echo glob*
또는ls glob*
또한 확장된 명령줄이 과도하게 채워질 가능성을 방지합니다(일부 셸의 경우 4K 길이 제한이 있음).
find가 오버킬처럼 느껴지고 일치할 가능성이 있는 파일 수가 적으면 stat:
if stat -t glob* >/dev/null 2>&1
then
echo found
else
echo not found
fi
좋아해요
exists() {
[ -e "$1" ]
}
if exists glob*; then
echo found
else
echo not found
fi
이는 읽기 쉽고 효율적입니다(많은 파일이 있는 경우는 제외).
가장 큰 단점은 보기보다 훨씬 미묘하다는 것이고, 가끔 긴 코멘트를 덧붙여야 할 때가 있습니다.
만약 일치하는 것이 있다면,"glob*"
는 셸에 항목은 셸에의확모일든항에전치다달니됩목이고장으로 됩니다.exists()
첫 번째 것은 확인하고 나머지는 무시합니다.
상대가 없다면,"glob*"
으로 전달됨exists()
그리고 그곳에도 존재하지 않는 것으로 밝혀졌습니다.
편집: 잘못된 긍정이 있을 수 있습니다. 주석을 참조하십시오.
#!/usr/bin/env bash
# If it is set, then an unmatched glob is swept away entirely --
# replaced with a set of zero words --
# instead of remaining in place as a single word.
shopt -s nullglob
M=(*px)
if [ "${#M[*]}" -ge 1 ]; then
echo "${#M[*]} matches."
else
echo "No such files."
fi
만약 당신이 글로벌 실패 세트를 가지고 있다면, 당신은 이 미친 것을 사용할 수 있습니다 (당신은 정말 해서는 안 됩니다).
shopt -s failglob # exit if * does not match
( : * ) && echo 0 || echo 1
또는
q=( * ) && echo 0 || echo 1
test-e는 끊어진 심볼 링크가 존재하지 않는다고 생각한다는 유감스러운 경고를 가지고 있습니다.그래서 당신은 그것들도 확인하는 것이 좋을 것입니다.
function globexists {
test -e "$1" -o -L "$1"
}
if globexists glob*; then
echo found
else
echo not found
fi
또 다른 해결책이 있습니다.
if [ "$(echo glob*)" != 'glob*' ]
이것은 저에게 잘 맞습니다.제가 놓친 코너 케이스가 있을지도 모릅니다.
flabdablet의 답변에 따르면, 다음과 같이 글로벌 확장을 셸에 남겨두면서 찾기 자체를 사용하는 것이 가장 쉬워 보입니다(꼭 빠를 필요는 없습니다).
find /some/{p,long-p}ath/with/*globs* -quit &> /dev/null && echo "MATCH"
또는에서.if
예:
if find $yourGlob -quit &> /dev/null; then
echo "MATCH"
else
echo "NOT-FOUND"
fi
미쿠의 생각을 바탕으로 미쿠의 대답을 다소 단순화하기 위해:
M=(*py)
if [ -e ${M[0]} ]; then
echo Found
else
echo Not Found
fi
파일을 반복하기 전에 파일이 있는지 테스트하려면 다음 패턴을 사용할 수 있습니다.
for F in glob*; do
if [[ ! -f $F ]]; then break; fi
...
done
glob이 일치하지 않으면 $F는 확장되지 않은 glob(이 경우 glob*)이 되고 동일한 이름의 파일이 존재하지 않으면 나머지 루프를 건너뜁니다.
Bash에서는 배열로 글러브할 수 있습니다. 글러브가 일치하지 않으면 배열에 기존 파일과 일치하지 않는 단일 항목이 포함됩니다.
#!/bin/bash
shellglob='*.sh'
scripts=($shellglob)
if [ -e "${scripts[0]}" ]
then stat "${scripts[@]}"
fi
: 있경우는경nullglob
세트,scripts
배열이 될이고, 은 빈배이될것며, 을사테합야니다해로 테스트해야 .[ "${scripts[*]}" ]
또는 와 함께[ "${#scripts[*]}" != 0 ]
대신.사용하거나 사용하지 않는 라이브러리를 작성하는 경우nullglob
원하실 겁니다.
if [ "${scripts[*]}" ] && [ -e "${scripts[0]}" ]
이 방법의 장점은 전역 작업을 반복하지 않고 작업할 파일 목록을 얻을 수 있다는 것입니다.
#!/bin/bash
set nullglob
touch /tmp/foo1 /tmp/foo2 /tmp/foo3
FOUND=0
for FILE in /tmp/foo*
do
FOUND=$((${FOUND} + 1))
done
if [ ${FOUND} -gt 0 ]; then
echo "I found ${FOUND} matches"
else
echo "No matches found"
fi
set -- glob*
if [ -f "$1" ]; then
echo "It matched"
fi
설명.
▁와 일치하지 않을 glob*
,그리고나서$1
을 합니다.'glob*'
시험은-f "$1"
사실이 아닐 것이다 왜냐하면glob*
파일이 없습니다.
이것이 대안보다 나은 이유
이것은 Shand 파생물인 KornShell과 Bash와 함께 작동합니다.하위 셸을 만들지 않습니다. $(..)
그리고.`...`
명령은 하위 셸을 생성합니다. 명령은 프로세스를 포크하므로 이 솔루션보다 느립니다.
Bash에서 처럼 (테스트 파일에는 다음과 같은 내용이 포함되어 있습니다.pattern
):
shopt -s nullglob
compgen -W *pattern* &>/dev/null
case $? in
0) echo "only one file match" ;;
1) echo "more than one file match" ;;
2) echo "no file match" ;;
esac
보다 훨씬 낫습니다.compgen -G
왜냐하면 우리는 더 많은 경우와 더 정확하게 구별할 수 있기 때문입니다.
" 드카드는하사수있다니습할용와나만일▁다▁only▁with▁one▁work▁it" 하나만 사용할 수 있습니다.*
.
이 혐오는 효과가 있는 것 같습니다.
#!/usr/bin/env bash
shopt -s nullglob
if [ "`echo *py`" != "" ]; then
echo "Glob matched"
else
echo "Glob did not match"
fi
아마도 sh가 아닌 bash가 필요할 것입니다.
이는 nullglob 옵션을 사용하면 일치하는 항목이 없을 경우 전역이 빈 문자열로 평가되기 때문에 작동합니다.따라서 echo 명령에서 비어 있지 않은 출력은 글로벌이 일치한다는 것을 나타냅니다.
확장된 글러브를 위한 솔루션(extglob
Bash:(으)로 표시:
bash -c $'shopt -s extglob \n /bin/ls -1U <ext-glob-pattern>'
하나 이상의 일치 항목이 있는 경우 종료 상태는 0이고, 일치 항목이 없는 경우 0이 아닙니다(2).표준 출력에는 일치하는 파일(및 따옴표로 묶은 공백이 포함된 파일 이름)이 줄로 구분된 새 목록이 포함됩니다.
또는 약간 다릅니다.
bash -c $'shopt -s extglob \n compgen -G <ext-glob-pattern>'
의 ls
- 기반 솔루션: 아마도 더 빠름(측정되지 않음), 출력에 공백이 따옴표로 묶이지 않은 파일 이름, 일치하는 항목이 없을 때는 코드 1을 종료합니다(2:vmx: 아님).
사용 예:
일치 항목 없음:
$ bash -c $'shopt -s extglob \n /bin/ls -1U @(*.foo|*.bar)'; echo "exit status: $?"
/bin/ls: cannot access '@(*.foo|*.bar)': No such file or directory
exit status: 2
하나 이상의 일치:
$ bash -c $'shopt -s extglob \n /bin/ls -1U @(*.ts|*.mp4)'; echo "exit status: $?"
'video1 with spaces.mp4'
video2.mp4
video3.mp4
exit status: 0
사용된 개념:
ls
코드 동작 ( behavior)-U
효율성을 위해, 그리고-1
출력 제어용).- 을 사용하지 .
extglob
현재 셸에서(종종 원하지 않음). - 를 합니다.
$
접두사를 붙여 다음과 같이 합니다.\n
확장된 글로벌 패턴이 다음과 다른 라인에 있도록 해석됩니다.shopt -s extglob
그렇지 않으면 확장된 글로벌 패턴은 구문 오류가 될 것입니다!
참고 1: 저는 이 솔루션을 위해 노력했습니다. 왜냐하면compgen -G "<glob-pattern>"
다른 답변에서 제안된 접근 방식은 브레이스 확장과 함께 원활하게 작동하지 않는 것 같습니다. 하지만 저는 좀 더 발전된 글로빙 기능이 필요했습니다.
참고 2: 확장 글로벌 구문에 대한 사랑스러운 리소스: extglob
둘다요.nullglob
그리고.compgen
일부 배시 셸에서만 유용합니다.
대부분의 셸에서 작동하는 (비재귀적) 솔루션은 다음과 같습니다.
set -- ./glob* # or /path/dir/glob*
[ -f "$1" ] || shift # remove the glob if present.
if [ "$#" -lt 1 ]
then echo "at least one file found"
fi
파일이 존재하는 경우 파일에 대한 작업을 수행할 수 있다고 가정합니다.
mapfile -t exists < <(find "$dirName" -type f -iname '*.zip'); [[ ${#exists} -ne 0 ]] && { echo "Zip files found" ; } || { echo "Zip files not found" ; }
그런 다음 파일을 사용하여 작업을 수행해야 할 경우 기존 배열을 순환할 수 있습니다.
(ls glob* &>/dev/null && echo Files found) || echo No file found
if ls -d $glob > /dev/null 2>&1; then
echo Found.
else
echo Not found.
fi
일치하는 항목이 많거나 파일 액세스 속도가 느릴 경우 시간이 많이 걸릴 수 있습니다.
ls | grep -q "glob.*"
가장 효율적인 솔루션은 아니지만(디렉토리에 파일이 많이 있는 경우 속도가 느릴 수 있음) 간단하고 읽기 쉬우며 정규식이 일반 Bashglob 패턴보다 강력하다는 장점이 있습니다.
[ `ls glob* 2>/dev/null | head -n 1` ] && echo true
언급URL : https://stackoverflow.com/questions/2937407/test-whether-a-glob-has-any-matches-in-bash
'programing' 카테고리의 다른 글
다중 ng-콘텐츠 (0) | 2023.05.12 |
---|---|
구성에서 원격에서 와 병합하도록 지정했지만 이러한 참조를 가져오지 않았습니다. (0) | 2023.05.12 |
Git에서 마지막 커밋을 두 개로 나누는 방법은 무엇입니까? (0) | 2023.05.12 |
어셈블리의 net standard, Version=2.0.0.0에 대한 참조를 추가해야 합니다. (0) | 2023.05.12 |
VBA를 사용하여 프로그래밍 방식으로 참조를 추가하는 방법 (0) | 2023.05.12 |