"*" 와일드카드를 사용할 때 파일 이동/복사 기능이 한 번에 하나의 파일만 이동하는 이유는 무엇입니까?

"*" 와일드카드를 사용할 때 파일 이동/복사 기능이 한 번에 하나의 파일만 이동하는 이유는 무엇입니까?
function mv1 { mv -n "$1" "targetdir" -v |wc -l ;}
mv1 *.png

.png찾은 모든 파일이 아닌 첫 번째 파일만 이동합니다 .

와일드카드와 일치하는 모든 파일에 명령을 적용하려면 어떻게 해야 합니까?

답변1

mv1 *.png먼저 와일드카드 패턴을 *.png일치하는 파일 이름 목록으로 확장한 다음 해당 파일 이름 목록을 함수에 전달합니다.

그런 다음 함수 내에서 다음을 $1의미합니다. 함수에 대한 첫 번째 인수를 가져오고, 공백이 포함된 부분을 분할하고, 와일드카드 문자가 포함된 공백으로 구분된 부분을 바꾸고 일치하는 파일 이름 목록으로 하나 이상의 파일 이름을 일치시킵니다. 복잡해 보이죠? 그렇습니다. 이 동작은 가끔 유용할 뿐이며 종종 문제가 됩니다. 이러한 분할 및 일치 동작은 큰따옴표 외부에서 발생하는 경우에만 발생하므로 $1수정이 쉽습니다. 큰따옴표를 사용하세요.변수 대체에는 항상 큰따옴표를 사용하세요.그렇게 하지 않을 타당한 이유가 있는 경우를 제외하고.

예를 들어, 현재 디렉터리에 두 개의 파일 A* algorithm.png과 가 포함된 경우 graph1.png는 함수에 첫 번째 인수로 전달되고 두 번째 인수로 mv1 *.png전달됩니다 . 그런 다음 과 로 나뉩니다 . 패턴이 와 일치하며 와일드카드 문자를 포함하지 않습니다. 따라서 함수는 , , 및 인수로 실행됩니다 . 해당 기능을 수정하면A* algorithm.pnggraph1.png$1A*algorithm.pngA*A* algorithm.pngalgorithm.pngmv-nA* algorithm.pngalgorithm.pngtargetdir-v

function mv1 { mv -n "$1" "targetdir" -v |wc -l ;}

그러면 첫 번째 파일이 올바르게 이동됩니다.

과정모두인수를 사용하면 첫 번째 인수뿐만 아니라 모든 인수를 처리하도록 쉘에 지시합니다. "$@"함수에 전달된 인수의 전체 목록을 의미하는 데 사용할 수 있습니다 .

function mv1 { mv -n "$@" "targetdir" -v |wc -l ;}

이는 거의 정확하지만 파일 이름이 문자로 시작하면 여전히 실패합니다 -. 왜냐하면 mv해당 인수를 옵션으로 처리하기 때문입니다. "이 지점 이후에는 더 이상 옵션이 없습니다"라고 알리려면 를 전달하십시오 --. mv이는 대부분의 명령이 지원하는 매우 일반적인 규칙입니다.

function mv1 { mv -n -v -- "$@" "targetdir" |wc -l ;}

남은 문제는 mv실패할 경우 파이프 왼쪽에 있는 명령의 종료 상태가 무시되기 때문에 이 함수가 성공 상태를 반환한다는 것입니다. Bash(또는 ksh)에서는 set -o pipefail파이프라인이 실패하도록 만드는 데 사용할 수 있습니다 . 이 옵션을 설정하면 동일한 셸에서 실행되는 다른 코드가 실패할 수 있으므로 함수에서 로컬로 설정해야 하며 이는 bash 4.4부터 가능합니다.

function mv1 {
  local -
  set -o pipefail
  mv -n -v -- "$@" "targetdir" | wc -l
}

이전 버전에서는 설정이 취약하므로 명시적으로 pipefail확인하는 것이 좋습니다 .PIPESTATUS

function mv1 {
  mv -n -v -- "$@" "targetdir" | wc -l
  ((!${PIPESTATUS[0] && !${PIPESTATUS[1]}}))
}

답변2

$1은 함수에 대한 첫 번째 인수입니다 *.png. 여기서는 . 나는 그것이 "$@"당신이 대신에 사용하고 싶은 것이라고 생각합니다 $1.

답변3

을 사용해야 합니다 mv1 \*.png.

기능과 상호 작용할 때 Linux 터미널은 별표를 명령에 직접 전달하지 않고 일치하는 첫 번째 매개 변수를 선택하여 해당 매개 변수를 명령에 전달합니다.

별표를 직접 통과하려면 백슬래시를 사용하여 별표를 이스케이프 처리해야 합니다.

관련 정보