파일을 찾아 특정 폴더에 복사하는 스크립트를 작성하려고 합니다. 파일 이름에는 공백과 기타 특수 문자가 포함되어 있습니다.
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
(와일드카드 패턴은 대부분 여러 파일 이름으로 확장될 가능성이 높음) 단일 명령을 사용하여 일부 대상 디렉터리에 복사할 수 있다는 사실에 의존합니다.
또한보십시오: