공백과 특수 문자가 포함된 cp는 터미널에서는 잘 작동하지만 스크립트에서는 작동하지 않습니다.

공백과 특수 문자가 포함된 cp는 터미널에서는 잘 작동하지만 스크립트에서는 작동하지 않습니다.

파일을 찾아 특정 폴더에 복사하는 스크립트를 작성하려고 합니다. 파일 이름에는 공백과 기타 특수 문자가 포함되어 있습니다.

a=$(ls ~/Downloads/ | grep $1)
a="'$a'"
a="~/Downloads/"$a
echo $a
cp $a ~/Documents/books/.

파일 이름을 인용하면 터미널에서 제대로 작동합니다. 그러나 스크립트에서는 이러한 단어가 별도의 매개변수로 처리됩니다. 위 스크립트에서 $a가 에코되면 다음이 제공됩니다.

~/Downloads/'Ian Goodfellow, Yoshua Bengio, Aaron Courville - Deep Learning [pre-pub version] (2016, MIT Press).pdf'

참조되는 파일 이름을 볼 수 있습니다. 위의 매개변수가 터미널의 cp에 전달되면 제대로 작동하지만 스크립트에서는 작동하지 않습니다. 도와주세요.

답변1

~/Downloads에서 으로 특정 파일을 복사 하려는 것 같습니다 ~/Documents/books.

가장 먼저 주목해야 할 점은 ~변수로 동작하지 않는다는 것입니다. 특히, 그렇습니다아니요참조할 때 홈 디렉터리의 경로로 확장합니다. 따라서 스크립트에서는 $HOME.

두 번째는 변수 값에 작은따옴표를 추가하는 것 같습니다 $a. 이는 불필요하며 "해당 파일이나 디렉터리가 없습니다"라는 오류만 발생합니다(파일 이름에 작은따옴표가 없기 때문입니다).

ls세 번째는 스크립트에서 사용 하지 않도록 노력해야 한다는 것입니다 . 예를 들어, 이 경우 $1파일 이름만 있으면 ~/Downloads검색할 필요가 전혀 없습니다. 또한 다음과 같은 grep $1여러 가지 이유로 사용에 문제가 있습니다.

  • grep주로 텍스트에 사용됨문서. 이론적으로 파일 이름에는 개행 문자가 포함될 수 있으므로 이름이 알려져 있거나 "양호"한 경우에만 파일 이름을 "grepping"할 수 있습니다.
  • $1따옴표로 묶지 않았으므로 grep공백이나 기타 특수문자가 포함된 경우 혼동을 일으킬 수 있습니다. 예를 들어, $1현재 디렉토리의 모든 파일 이름으로 확장됩니다.*
  • 문자열이 $1대시로 시작하면 옵션으로 처리됩니다 grep.

따라서 스크립트는 다음과 같이 작성할 수 있습니다.

#!/bin/sh

name="$HOME/Downloads/$1"

printf 'The filename is "%s"\n' "$name"

cp "$name" "$HOME/Documents/books"

여기서 명령은 printf선택한 파일의 이름을 출력하는 것입니다. 그래요산출이름 주위에 큰따옴표가 있지만 이름에는 큰따옴표가 있습니다.아니요안에 큰따옴표가 있습니다. 대신 $name마지막 줄에 통화 내용을 꼭 인용했습니다 . cp사실 인용해야겠어요모두그렇지 않으면 확장으로 인해 쉘이 변수 값을 분할하게 된다는 것을 알고 있습니다.

이 스크립트를 다음과 같이 사용할 수 있습니다.

./script.sh 'Ian Goodfellow, Yoshua Bengio, Aaron Courville - Deep Learning [pre-pub version] (2016, MIT Press).pdf'

파일 이름에는 셸에 특수한 공백과 문자가 포함되어 있으므로 따옴표로 묶어야 합니다.

스크립트가 명령줄에 제공된 단어가 포함된 파일을 찾도록 하려면 다음과 같이 말할 수 있습니다.

./script.sh Goodfellow

그런 다음 주어진 문자열을 와일드카드 패턴으로 사용합니다.

#!/bin/sh

for name in "$HOME/Downloads"/*"$1"*.pdf; do
    printf 'Will copy the file "%s"\n' "$name"
    cp "$name" "$HOME/Documents/books"
done

이제 스크립트는 첫 번째 매개변수를 사용하여 파일 이름에 지정된 문자열이 포함된 모든 파일을 반복합니다 .pdf. ~/Downloads이러한 각 파일은 에 복사됩니다 ~/Documents/books.

cp -v파일이 자세하게 복사되는 Unix를 사용하는 경우 스크립트 범위가 더욱 좁아질 수 있습니다.

#!/bin/sh

cp -v "$HOME/Downloads"/*"$1"*.pdf "$HOME/Documents/books"

이렇게 하면 지정된 패턴과 일치하는 파일 이름을 더 이상 반복하지 않으므로 사용자가 직접 출력 형식을 지정하는 것을 방지할 수 있습니다("Will copy..."). 대신, 우리는 여러 파일 이름이 주어지면 cp(와일드카드 패턴은 대부분 여러 파일 이름으로 확장될 가능성이 높음) 단일 명령을 사용하여 일부 대상 디렉터리에 복사할 수 있다는 사실에 의존합니다.


또한보십시오:

관련 정보