저는 bash 스크립팅을 처음 접했고 사용자 입력을 받아 디렉터리의 모든 파일을 다른 디렉터리로 하드링크하는 스크립트를 만들고 싶습니다. 지금까지 나는 이것을 가지고 있습니다 :
read -p "What directory do you want to link? " dir
items=$(ls -m $dir -Q | tr -d '\n'' ')
read -p "Where do you want to link the files? " outdir
echo "Linking files: $items to: $outdir"
read -p "Continue? (y/N) " confirmation
if [ $confirmation == "y" ] || [ $confirmation == "Y" ]; then
ln $dir/{$items} $outdir
else
kill -SIGTERM $$
fi
내가 입력 /home/ethan/test
하고 /home/ethan/test2
얻을 때ln: failed to access '/home/ethan/test/{"test1","test2"}': No such file or directory
또한 그 내용은 제가 Arch에 가지고 있는 /home/ethan/test
두 개의 파일입니다 .test1
test2
이 작업을 수행하려면 무엇을 변경해야 하는지 알아내는 데 도움을 줄 수 있는 사람이 있나요? 감사해요.
답변1
이와 같은 짧은 유틸리티 스크립트의 경우 권장합니다아니요대화형으로 만드세요. 사용자는 설명하는 방식으로 복사하려는 디렉터리를 정확히 알고 있을 수 있으며, 사용자가 명령줄에서 탭 완성 및/또는 파일 이름 글로빙을 사용하도록 허용하면 다음을 입력하는 것과 동일한 결과를 얻을 가능성이 더 높아집니다. 메모리에서 가져온 매개변수와 비교하면 매개변수가 정확합니다.
또한, 나는 ls
이외의 다른 것을 사용하지 않을 것입니다파일 목록 보기. ls
파일 이름을 읽기 위해 스크립트에서 사용 하지 마십시오 . 파일 이름 글로빙 패턴을 사용하는 것이 가장 좋습니다. 이에 대해서는 다른 Q&A에서 자세히 설명합니다.왜 `ls`를 구문 분석하지 *않나요*(그리고 어떻게 수행합니까)?
스크립트를 종료하려면 끝까지 실행하거나 를 사용하십시오 exit
. kill
또한 일반적으로 단어 분리 및 원치 않는 파일 이름 글로빙을 방지하려면 모든 변수 확장을 큰따옴표로 묶으십시오.언제 큰따옴표가 필요합니까?).
중괄호 확장 내에서 쉘 변수를 사용하려고 시도하면 특정 오류가 발생합니다. 이는 불가능합니다 bash
(예를 들어중괄호와 변수 확장을 한 줄에 결합).
사용자가 이름이 대시로 시작하는 디렉토리를 사용하려는 경우 추가 문제가 발생합니다.
ls
출력을 사용하여 중괄호 확장에 사용되는 일종의 목록(쉼표, 줄 바꿈 및 기타 문자가 포함된 파일 이름을 억제함)에 결합하는 대신 함수나 셸 스크립트를 셸로 래핑하는 옵션을 rsync
사용 합니다. --link-dest
편의:
#!/bin/sh -
# The two expected arguments are
# 1. an existing source directory, and
# 2. a possibly existing destination directory
if [ ! -d "$1" ]; then
printf 'Not a directory: %s\n' "$1" >&2
exit 1
fi
if [ -e "$2" ] && [ ! -d "$2" ]; then
printf 'Not a directory: %s\n' "$2" >&2
exit 1
fi
rsync -a --link-dest="$(readlink -f -- "$1")" -- "$1/" "$2"
먼저 사용자가 유효한 매개변수를 제공하는지 확인해야 합니다. 이 스크립트의 경우 이는 첫 번째 인수(소스)가 기존 디렉터리여야 하고 두 번째 인수(대상)가 존재하지 않거나 디렉터리여야 함을 의미합니다.
옵션과 함께 소스 디렉토리의 절대 경로가 readlink -f
사용되는지 확인하기 위해 사용합니다. 그렇지 않으면 대상 디렉토리 경로에 상대적인 경로를 해석합니다. 이 유틸리티는 표준은 아니지만 일반적입니다.--link-dest
rsync
readlink
이 방식을 사용하면 rsync
소스 디렉토리가 대상 디렉토리 경로에서 반복적으로 다시 생성되고 (소스와 대상이 동일한 파일 시스템에 있는 경우) 디렉토리가 아닌 파일이 하드 링크됩니다. 소스 및 대상 경로가 다른 파일 시스템에 있는 경우 소스 디렉토리 경로는 재귀적입니다.복사대신 하드 링크가 생성되지 않습니다.
호출에서 소스 매개변수 끝에 슬래시를 추가했습니다 rsync
. 소스 디렉토리를 복사하기 위해 이 작업을 수행합니다.콘텐츠, 디렉토리 자체가 아닌.
특별한 기능을 사용하지 않기 때문에 /bin/sh
스크립트가 아닌 스크립트로 스크립트를 작성 했습니다 .bash
bash
시험:
$ tree src
src
|-- data.dat
|-- subdir1
| `-- myfile.txt
`-- subdir2
`-- myfile.txt
2 directories, 3 files
$ linkcp src dst1
파일당 링크 수는 2개입니다.
$ ls -l dst1
total 8
-rw-r--r-- 2 myself wheel 0 Apr 6 07:47 data.dat
drwxr-xr-x 2 myself wheel 512 Apr 6 07:47 subdir1
drwxr-xr-x 2 myself wheel 512 Apr 6 07:47 subdir2
$ ls -l dst1/subdir*
dst1/subdir1:
total 0
-rw-r--r-- 2 myself wheel 0 Apr 6 07:47 myfile.txt
dst1/subdir2:
total 0
-rw-r--r-- 2 myself wheel 0 Apr 6 07:47 myfile.txt
$ linkcp src dst2
src
구조의 또 다른 복사본을 만들면 링크 수가 이제 3으로 늘어납니다.
$ ls -l dst2
total 8
-rw-r--r-- 3 myself wheel 0 Apr 6 07:47 data.dat
drwxr-xr-x 2 myself wheel 512 Apr 6 07:47 subdir1
drwxr-xr-x 2 myself wheel 512 Apr 6 07:47 subdir2
$ ls -l dst2/subdir*
dst2/subdir1:
total 0
-rw-r--r-- 3 myself wheel 0 Apr 6 07:47 myfile.txt
dst2/subdir2:
total 0
-rw-r--r-- 3 myself wheel 0 Apr 6 07:47 myfile.txt