“mv”가 자동으로 실패하게하는 방법이 있습니까? `foo*’: No such file

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]경우 fooxfooy파일 대신 실수로 파일을 이동했을 수 있습니다 .

이제 문제가없는 쉘 (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)

zshBourne 버그가 없으며 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에서 :

bashnullglob하나의 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

nullglobPOSIX 에는 옵션 이 없으며 sh위치 매개 변수 이외의 배열은 없습니다. 그래 브가 일치하는지 여부를 감지하는 데 사용할 수있는 트릭이 있습니다.

set -- foo[*] foo*
if [ "$1$2" != 'foo[*]foo*' ]; then
  shift
  mv -- "$@" ~/bar/
fi

a foo[*]foo*glob 을 모두 사용하여 일치하는 파일이없는 경우와 호출 할 수있는 하나의 파일이있는 경우 foo*(할 set -- foo*수없는)를 구별 할 수 있습니다 .

더 많은 독서 :


답변

아마도 가장 좋지는 않지만 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