mv foo* ~/bar/
파일이 일치하지 않으면 같은 명령 이 stderr에이 메시지를 생성합니다 foo*
.
mv: cannot stat `foo*': No such file or directory
그러나 스크립트 에서이 작업을 수행하는 것이 좋습니다. 로그에서 해당 메시지를 생략하고 싶습니다.
mv
아무것도 움직이지 않아도 조용히 말할 수 있는 좋은 방법이 있습니까?
답변
이것을 찾고 있습니까?
$ mv file dir/
mv: cannot stat ‘file’: No such file or directory
$ mv file dir/ 2>/dev/null
# <---- Silent ----->
답변
실제로, 나는 뮤팅 mv
이 좋은 접근 방법 이라고 생각하지 않습니다 (관심있는 다른 것들에 대해서도보고 할 수 있음을 기억하십시오 … 누락 ~/bar
). glob 표현식이 결과를 반환하지 않는 경우에만 음소거하고 싶습니다. 실제로 오히려 전혀 실행하지 마십시오.
[ -n "$(shopt -s nullglob; echo foo*)" ] && mv foo* ~/bar/
매우 매력적으로 보이지 않으며에서 작동합니다 bash
.
또는
[ 'foo*' = "$(echo foo*)" ] || mv foo* ~/bar/
당신이 세트 에 bash
있는 것을 제외하고 만 nullglob
. 그래 브 패턴의 3 배 반복 가격을 지불합니다.
답변
find . -maxdepth 1 -name 'foo*' -type f -print0 | xargs -0r mv -t ~/bar/
— GNU mv
에는 “대상 우선”옵션 ( -t
)이 있으며 xargs
입력이 없으면 명령 실행을 건너 뛸 수 있습니다 ( -r
). 의 사용 -print0
과 -0
상응하여 파일 이름에 공백이 다른 “재미”물건을 포함 할 때 엉망이되지 않을 것 확인합니다.
답변
실제로는 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*
수없는)를 구별 할 수 있습니다 .
더 많은 독서 :
- nullglob가 기본이 아닌 이유는 무엇입니까?
- Austin Group 메일 링리스트에 대한이 관련 토론 (Austin Group은 POSIX 사양을 유지하는 기관입니다)
답변
아마도 가장 좋지는 않지만 find
명령을 사용 하여 폴더가 비어 있는지 여부를 확인할 수 있습니다 .
find "foo*" -type f -exec mv {} ~/bar/ \;
답변
이 오류는 bash의 동작에 따라 일치하지 않는 globs를 확장하기 때문에 bash를 사용한다고 가정합니다. (비교하여, zsh는 일치하지 않는 glob를 확장하려고 할 때 오류를 발생시킵니다.)
그렇다면 다음 해결 방법은 어떻습니까?
ls -d foo* >/dev/null 2>&1 && mv foo* ~/bar/
이것은 자동으로 무시 mv
하는 경우 ls -d foo*
경우 여전히 오류를 기록하면서 실패 ls foo*
성공하지만이 mv
실패합니다. ( 권한 부족, FS 관련 문제 등) 존재하지 않는 ls foo*
다른 이유로 실패 foo*
할 수 있으므로이 솔루션에서는 이러한 조건을 자동으로 무시합니다.
답변
예를 들어 할 수 있습니다
mv 1>/dev/null 2>&1 foo* ~/bar/
또는 mv foo* ~/bar/ 1&>2
자세한 내용은 다음을 참조하십시오 : http://mywiki.wooledge.org/BashFAQ/055