
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.png
graph1.png
$1
A*
algorithm.png
A*
A* algorithm.png
algorithm.png
mv
-n
A* algorithm.png
algorithm.png
targetdir
-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 터미널은 별표를 명령에 직접 전달하지 않고 일치하는 첫 번째 매개 변수를 선택하여 해당 매개 변수를 명령에 전달합니다.
별표를 직접 통과하려면 백슬래시를 사용하여 별표를 이스케이프 처리해야 합니다.