중괄호 확장 및 * 확장

중괄호 확장 및 * 확장

작업 디렉터리에 djvu 파일이 하나만 있다고 가정합니다. .bk파일 이름 끝에 추가 내용이 있는 파일 로 파일을 백업하고 싶습니다 . cp *.djvu{,.bk}djvu 파일을 이라는 파일에 복사하세요 *.djvu.bk. *백업 파일 이름에 확장자가 없는 이유는 무엇인가요? 어떻게 그래?

답변1

무슨 일이 일어나는지는 bash가 먼저 확장된 *.djvu{,.bk}다음 *.djvu *.djvu.bkglob이 확장된다는 것입니다. 이는 귀하가 관찰하고 있는 내용을 설명합니다. 귀하의 경우 는 *.djvu기존 파일과 일치 foo.djvu하고 해당 파일로 확장되지만 *.djvu.bk어떤 파일과도 일치하지 않으므로 자체적으로 확장됩니다 *.djvu.bk.

확장 순서는 bash 문서에 지정되어 있습니다.

The order of expansions is: brace expansion, tilde  expansion,  parame‐
ter,  variable  and arithmetic expansion and command substitution (done
in a left-to-right fashion), word splitting, and pathname expansion.

복사 명령을 다음과 같이 다시 작성하는 것이 좋습니다.

for f in *.djvu; do cp -- "$f" "$f".bk; done

또는 명시적인 for 루프의 구문 오버헤드를 방지하려면 다음을 수행하세요.

parallel -j1 cp -- {} {}.bk ::: *.djvu

(다시 생각해 보세요. 그다지 짧은 것은 아닙니다.)

"확장 방법"이라는 하위 질문에 대답하려면 하위 명령을 사용할 수 있습니다(예: foo.djvu및 만 포함하는 디렉토리 에서 bar.djvu).

$ echo $(echo *.djvu){,.bk}
bar.djvu foo.djvu bar.djvu foo.djvu.bk

그러나 이는 위의 for 루프나 병렬 호출만큼 안전하지 않습니다. 공백이 포함된 파일 이름에서는 충돌이 발생합니다.

답변2

중괄호 확장은 별도의 단어를 생성하는 반면 와일드카드 확장은 와일드카드 패턴이 이미 별도의 단어에 있는 경우 끝에 발생하므로 와일드카드 확장 전에 중괄호 확장이 발생합니다. (어쨌든 반대 방향으로 발생하면 cp *.djvu{,.bk}이름이 it로 끝나는 파일이 없기 때문에 일치하는 항목이 없으며 .djvu{,.bk}중괄호 확장은 두 단어 *.dvju와 를 생성합니다 *.djvu.bk.) 따라서 첫 번째 단어는 cp *.djvu{,.bk}로 확장되고 cp *.djvu *.djvu.bk다음에는 각각 하나가 확장됩니다. 와일드카드 포함 와일드카드가 하나 이상의 파일과 일치하면 단어가 확장됩니다. 일치하는 파일은 있지만 *.djvu일치하는 파일이 *.djvu.bk없으므로 cp a.djvu b.djvu *.djvu.bk.

일치하는 file 이 있는 경우 *.djvu.bk이 와일드카드 패턴도 확장되므로 다음과 같은 결과가 됩니다 cp a.djvu b.djvu a.djvu.bk c.djvu.bk. 및 파일에 대해 작업하는 것이 목적이지만 cp두 패턴 중 어느 것도 일치하지 않도록 허용하는 경우 ksh를 사용할 수 있습니다. 확장된 패턴:*.djvu*.djvu.bk

shopt -s extglob
cp *.djvu?(.bk) somedir/

하지만 그건 당신이 하고 싶은 일이 아닙니다. 인수를 확장하여 원하는 것을 얻을 수 없습니다 . 각 파일에 대해 각각 올바른 대상을 사용하여 별도의 명령을 실행 cp해야 합니다 . 하나의 명령으로 충분한 유일한 경우는 파일 이 하나뿐 이므로 단일 파일로 확장되는 경우입니다. 이 경우 명령을 입력하는 가장 쉬운 방법은 모드로 들어간 다음(입력 시작 ) bash에게 +를 눌러 확장하고 , 를 눌러 후행 공백을 제거하고 Enter를 누르라고 지시하는 것입니다 .cp.djvucp.djvu*.djvucp *.djvuCtrlX *Backspace{,.bk}

여러 파일을 복사하려면 cp어떤 식으로든 호출을 반복하거나 이름 패턴을 기반으로 파일을 복사할 수 있는 다른 도구를 사용해야 합니다.

Bash에서 루프를 작성하는 것은 매우 간단합니다.

for x in *.djvu; do cp "$x" "$x.bk"; done

사용할 수 있는 또 다른 도구는 다음과 같습니다.공원. 여기에 입력하는 것이 그다지 재미는 없습니다.

pax -rw -s'/$/.bk/' *.djvu .

Zsh는영점이런 종류의 작업을 위해. 다음 위치에 로드하세요 .zshrc.

autoload -U zmv
alias zcp='zmv -C' zln='zmv -L'

그런 다음 실행

zcp '*.djvu' '$f.bk'

관련 정보