글로브가 bash에서 일치하는지 테스트
나는 하나의 파일의 존재를 확인하려는 경우, 나는 그것을 사용하기 위해 테스트 할 수 있습니다 test -e filename
또는 [ -e filename ]
.
글로브가 있고 글로브와 이름이 일치하는 파일이 있는지 알고 싶습니다. glob은 0 개의 파일과 일치하거나 (이 경우 아무 것도 할 필요가 없음) 1 개 이상의 파일과 일치 할 수 있습니다 (이 경우 무언가를 수행해야 함). 글로브에 일치하는 것이 있는지 어떻게 테스트 할 수 있습니까? (나는 얼마나 많은 일치 항목이 있는지 상관하지 않으며 하나의 if
명령문으로 루프 없이이 작업을 수행 할 수 있다면 가장 좋습니다 (간단히 읽을 수 있기 때문에).
( test -e glob*
글로브 파일이 둘 이상 일치하면 실패합니다.)
배쉬 전용 솔루션 :
compgen -G "<glob-pattern>"
패턴을 이스케이프하면 패턴이 미리 확장됩니다.
종료 상태는 다음과 같습니다.
- 일치하지 않는 경우 1
- '하나 이상의 일치 항목'은 0
stdout
glob와 일치하는 파일 목록입니다 .
간결함과 잠재적 부작용 최소화 측면에서 이것이 최선의 선택이라고 생각합니다.
업데이트 : 사용 요청 예.
if compgen -G "/tmp/someFiles*" > /dev/null; then
echo "Some files exist."
fi
nullglob 쉘 옵션은 실제로 bashism입니다.
nullglob 상태를 지루하게 저장하고 복원 할 필요가 없도록, glob를 확장하는 서브 쉘 내에서만 설정합니다.
if test -n "$(shopt -s nullglob; echo glob*)"
then
echo found
else
echo not found
fi
더 나은 휴대 성과보다 유연한 글 로빙을 위해서는 find를 사용하십시오 :
if test -n "$(find . -maxdepth 1 -name 'glob*' -print -quit)"
then
echo found
else
echo not found
fi
명시 적 -print -quit 조치는 기본 내재적 -print 조치 대신 찾기에 사용 되므로 찾기 기준과 일치하는 첫 번째 파일을 찾은 즉시 찾기 가 종료됩니다. 많은 파일이 일치하는 경우 또는 이보다 훨씬 빠르게 실행되어야 하며 확장 된 명령 행을 과도하게 채울 가능성을 피할 수 있습니다 (일부 쉘의 길이 제한은 4K입니다).echo glob*
ls glob*
경우 찾기가 과도 같은 느낌 가능성에 맞게 파일의 수가 작고, 사용 합계 :
if stat -t glob* >/dev/null 2>&1
then
echo found
else
echo not found
fi
#!/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
나는 좋아한다
exists() {
[ -e "$1" ]
}
if exists glob*; then
echo found
else
echo not found
fi
This is both readable and efficient (unless there are a huge number of files).
The main drawback is that it's much more subtle than it looks, and I sometimes feel compelled to add a long comment.
If there's a match, "glob*"
is expanded by the shell and all the matches are passed to exists()
, which checks the first one and ignores the rest.
If there's no match, "glob*"
is passed to exists()
and found not to exist there either.
Edit: there may be a false positive, see comment
If you have globfail set you can use this crazy (which you really should not)
shopt -s failglob # exit if * does not match
( : * ) && echo 0 || echo 1
or
q=( * ) && echo 0 || echo 1
test -e has the unfortunate caveat that it considers broken symbolic links to not exist. So you may want to check for those, too.
function globexists {
test -e "$1" -o -L "$1"
}
if globexists glob*; then
echo found
else
echo not found
fi
I have yet another solution:
if [ "$(echo glob*)" != 'glob*' ]
This works nicely for me. Are there some corner cases I miss?
To simplify The MYYN's answer somewhat, based on his idea:
M=(*py)
if [ -e ${M[0]} ]; then
echo Found
else
echo Not Found
fi
Based on flabdablet's answer, for me it looks like easiest (not necessarily fastest) is just to use find itself, while leaving glob expansion on shell, like:
find /some/{p,long-p}ath/with/*globs* -quit &> /dev/null && echo "MATCH"
Or in if
like:
if find $yourGlob -quit &> /dev/null; then
echo "MATCH"
else
echo "NOT-FOUND"
fi
In Bash, you can glob to an array; if the glob didn't match, your array will contain a single entry that doesn't correspond to an existing file:
#!/bin/bash
shellglob='*.sh'
scripts=($shellglob)
if [ -e "${scripts[0]}" ]
then stat "${scripts[@]}"
fi
Note: if you have nullglob
set, scripts
will be an empty array, and you should test with [ "${scripts[*]}" ]
or with [ "${#scripts[*]}" != 0 ]
instead. If you're writing a library that must work with or without nullglob
, you'll want
if [ "${scripts[*]}" ] && [ -e "${scripts[0]}" ]
An advantage of this approach is that you then have the list of files you want to work with, rather than having to repeat the glob operation.
This abomination seems to work:
#!/usr/bin/env bash
shopt -s nullglob
if [ "`echo *py`" != "" ]; then
echo "Glob matched"
else
echo "Glob did not match"
fi
It probably requires bash, not sh.
This works because the nullglob option causes the glob to evaluate to an empty string if there are no matches. Thus any non-empty output from the echo command indicates that the glob matched something.
I did not see this answer, so I thought I'd put it out there:
set -- glob*
[ -f "$1" ] && echo "found $@"
if ls -d $glob > /dev/null 2>&1; then
echo Found.
else
echo Not found.
fi
Note that this can be very time cosuming if there are a lot of matches or file access is slow.
#!/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
Explanation
When there isn't a match for glob*
, then $1
will contain 'glob*'
. The test -f "$1"
won't be true because the glob*
file doesn't exist.
Why this is better than alternatives
This works with sh and derivates: ksh and bash. It doesn't create any sub-shell. $(..)
and `...`
commands create a sub-shell; they fork a process, and therefore are slower than this solution.
(ls glob* &>/dev/null && echo Files found) || echo No file found
ls | grep -q "glob.*"
Not the most efficient solution (if there's a ton of files in the directory it might be slowish), but it's simple, easy to read and also has the advantage that regexes are more powerful than plain bash glob patterns.
[ `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' 카테고리의 다른 글
Javascript에서 창, 화면 및 문서의 차이점은 무엇입니까? (0) | 2020.05.05 |
---|---|
종료 메시지를 만드는 방법 (0) | 2020.05.05 |
TypeScript 함수 오버로딩 (0) | 2020.05.05 |
MySQL에서 자동 증가 필드를 사용하여 행을 복사하고 동일한 테이블에 삽입하는 방법은 무엇입니까? (0) | 2020.05.05 |
`scp`와`rsync`는 어떻게 다릅니 까? (0) | 2020.05.05 |