실제로는 foo*
해당 파일 이름을 일치하는 파일 이름 목록으로 확장하는 쉘 이므로, mv
자체적으로 수행 할 수있는 작업은 거의 없습니다.
여기서 문제는 glob가 일치하지 않을 때 bash
(대부분의 다른 Bourne과 같은 쉘, 버그가있는 동작이 실제로 70 년대 후반 Bourne 쉘에 의해 도입 됨) 일부 패턴을 명령에 전달한다는 것입니다.
따라서 여기에서 foo*
어떤 파일과도 일치하지 않으면 (Bourne 이전 쉘 및 여러 현대 쉘과 같이) 명령을 중단하는 대신 쉘은 그대로의 foo*
파일을로 전달하여 mv
기본적으로 mv
라는 파일을 이동하도록 요청 합니다 foo*
.
해당 파일이 없습니다. 일치하면 실제로 패턴과 일치했을 것이므로 mv
오류를보고합니다. 패턴이 foo[xy]
대신 mv
발생한 foo[xy]
경우 foox
및 fooy
파일 대신 실수로 파일을 이동했을 수 있습니다 .
이제 문제가없는 쉘 (pre-Bourne, csh, tcsh, fish, zsh, bash -O failglob)에서도 여전히 오류가 발생 mv foo* ~/bar
하지만 이번에는 쉘 에서 오류가 발생합니다 .
일치하는 파일이없는 경우 오류가 아닌 것으로 간주 하고이 경우 foo*
아무것도 움직이지 않으려면 먼저 파일 목록을 작성하십시오 ( nullglob
옵션 옵션을 사용하여 오류가 발생하지 않는 방식 으로) 일부 쉘), 그리고 호출 만 mv
목록이 비어 있지 않습니다.
즉, 숨어보다 더 나은 것 모두 의 오류를 mv
(추가하는 2> /dev/null
것처럼 것) mv
다른 이유로 실패, 당신은 아마 아직도 이유를 알고 싶어.
zsh에서
files=(foo*(N)) # where the N glob qualifier activates nullglob for that glob
(($#files == 0)) || mv -- $files ~/bar/
또는 임시 변수를 사용하지 않으려면 익명 함수를 사용하십시오.
() { (($# == 0)) || mv -- "$@" ~/bar/; } foo*(N)
zsh
Bourne 버그가 없으며 glob가 일치하지 않고 nullglob
옵션이 활성화 되지 않은 경우 명령을 실행하지 않고 오류를보고하는 쉘 중 하나 이므로 zsh
오류를 숨기고 복원 할 수 있습니다 stderr mv
때문에 mv
일치하지 않는 globs에 대한 오류는 없지만 여전히 오류가 표시됩니다.
(mv 2>&3 foo* ~/bar/) 3>&2 2>&-
또는 glob가 너무 많은 파일로 확장 zargs
되면 문제를 피할 수 foo*
있습니다.
autoload zargs # best in ~/.zshrc
zargs -r -- foo* -- mv -t ~/bar # here assuming GNU mv for its -t option
ksh93에서 :
files=(~(N)foo*)
((${#files[#]} == 0)) || mv -- "${files[@]}" ~/bar/
bash에서 :
bash
nullglob
하나의 glob에만 사용할 수있는 구문이 없으며 failglob
옵션이 취소 nullglob
되므로 다음과 같은 것이 필요합니다.
saved=$(shopt -p nullglob failglob) || true
shopt -s nullglob
shopt -u failglob
files=(foo*)
((${#files[@]} == 0)) || mv -- "${files[@]}" ~/bar/
eval "$saved"
또는 서브 쉘에서 옵션을 설정하여 저장하기 전에 저장 한 후 나중에 복원해야합니다.
(
shopt -s nullglob
shopt -u failglob
files=(foo*)
((${#files[@]} == 0)) || mv -- "${files[@]}" ~/bar/
)
에서 yash
(
set -o nullglob
files=(foo*)
[ "${#files[@]}" -eq 0 ] || mv -- "${files[@]}" ~/bar/
)
에서 fish
피쉬 쉘에서 nullglob 동작은이 set
명령 의 기본값 이므로 다음과 같습니다.
set files foo*
count $files > /dev/null; and mv -- $files ~/bar/
POSIXly
nullglob
POSIX 에는 옵션 이 없으며 sh
위치 매개 변수 이외의 배열은 없습니다. 그래 브가 일치하는지 여부를 감지하는 데 사용할 수있는 트릭이 있습니다.
set -- foo[*] foo*
if [ "$1$2" != 'foo[*]foo*' ]; then
shift
mv -- "$@" ~/bar/
fi
a foo[*]
와 foo*
glob 을 모두 사용하여 일치하는 파일이없는 경우와 호출 할 수있는 하나의 파일이있는 경우 foo*
(할 set -- foo*
수없는)를 구별 할 수 있습니다 .
더 많은 독서 :
mv foo* ~/bar/ 2> /dev/null
?