저는 다음 과제를 수행 중이며 내 프로그램에 대한 질문이 있습니다.
아래에 설명된 대로 파일을 복사하는 쉘 스크립트를 작성하십시오. 접미사는 명령줄 인수로 전송되어야 합니다. 지정된 접미사가 적합한 현재 디렉터리의 각 파일에 대해 사용자에게 해당 파일을 저장해야 하는지 묻는 메시지가 표시됩니다. 대답이 '예'이면 파일을 백업 디렉터리에 복사해야 합니다. 디렉터리가 존재하지 않으면 새로 만들어야 합니다.
이것이 내가 한 일입니다:
#!/bin/sh
usage() {
echo "Usage : prog.sh <POSTFIX> " >&2
exit 1
}
if [ $# -ne 1 ]; then
usage
fi
list=$(ls)
for name in $list; do
case $name in
*.$@)
printf "Do you want to save the file ?\n"
read answer
case $answer in
Yes|yes|y)
ls backup 2>/dev/null || mkdir backup
mv $name backup
;;
No|no|n);;
esac ;;
esac
done
다음 폴더가 있다고 가정해 보겠습니다. (백업 디렉터리로 이동됩니다.)
bar.txt foobar.txt foo.txt mbar.txt
이것은 내 결과입니다.
Do you want to save the file ?
y
Do you want to save the file ?
y
bar.txt // Why is it printing the file during the output ?
Do you want to save the file ?
y
bar.txt foobar.txt // ??
Do you want to save the file ?
y
bar.txt foobar.txt foo.txt // ??
ls backup 2>/dev/null || mkdir backup
(대신에 ) 이렇게 쓸 수 있다는 걸 알아요
if [ ! -d backup ] ; then
mkdir backup
fi
하지만 내 프로그램이 출력 중에 백업으로 이동된 파일을 인쇄하는 이유를 알고 싶습니다.
답변1
ls backup 2>/dev/null
디렉토리로 이동한 각 파일에 대해 작업을 수행했기 때문에 해당 파일이 backup
다음에 ls
표시됩니다 .
그런데 전체 스크립트를 다음과 같은 단일 명령으로 바꿀 수 있습니다 rsync
.
rsync --include='*.{txt,csv,xyz}' /path/to/source/* /path/to/backup/
바라보다man rsync
동기화 후 삭제 방법에 대해 자세히 알아보세요.
답변2
다음 줄 때문입니다.
ls backup 2>/dev/null
stdout이 아닌 stderr만 리디렉션합니다. 다음을 수행해야 합니다.
ls backup >/dev/null 2>&1 || mkdir backup
그렇지 않으면:
mkdir -p backup
또한 shellcheck에서 표시되는 경고에도 주의를 기울여야 합니다.
$ shellcheck ./p.sh
In ./p.sh line 18:
read answer
^--^ SC2162: read without -r will mangle backslashes.
In ./p.sh line 24:
mv $name backup
^---^ SC2086: Double quote to prevent globbing and word splitting.
Did you mean:
mv "$name" backup
For more information:
https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...
https://www.shellcheck.net/wiki/SC2162 -- read without -r will mangle backs...
답변3
Bash가 허용된다면 다음과 같이 할 것입니다:
#!/usr/bin/env bash
if (( $# == 0 )); then
echo "usage: ${0##*/} extension ..." >&2
exit 1
fi
dir=./backup
mkdir -p "$dir"
# if the script is called like `script.sh foo bar baz`
# then $pattern is `@(*foo|*bar|*baz)`
pattern=$(
set -- "${@/#/*}"
IFS='|'
echo "@($*)"
)
shopt -s nocasematch
for file in *; do
# right-hand side is specifically unquoted
if [[ "$file" == $pattern ]]; then
read -p "Move file '$file'? [y/N] " ans
if [[ "$ans" == Y* ]]; then
mv -i -v "$file" "$dir"
fi
fi
done
과제이기 때문에 구체적인 질문을 하기 전에 이해가 안 되는 부분을 좀 조사해 보세요. 이것배쉬 매뉴얼좋은 출발점입니다.