디렉터리의 파일을 연결하는 스크립트에 대한 도움이 필요합니다.

디렉터리의 파일을 연결하는 스크립트에 대한 도움이 필요합니다.

저는 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두 개의 파일입니다 .test1test2

이 작업을 수행하려면 무엇을 변경해야 하는지 알아내는 데 도움을 줄 수 있는 사람이 있나요? 감사해요.

답변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-destrsyncreadlink

이 방식을 사용하면 rsync소스 디렉토리가 대상 디렉토리 경로에서 반복적으로 다시 생성되고 (소스와 대상이 동일한 파일 시스템에 있는 경우) 디렉토리가 아닌 파일이 하드 링크됩니다. 소스 및 대상 경로가 다른 파일 시스템에 있는 경우 소스 디렉토리 경로는 재귀적입니다.복사대신 하드 링크가 생성되지 않습니다.

호출에서 소스 매개변수 끝에 슬래시를 추가했습니다 rsync. 소스 디렉토리를 복사하기 위해 이 작업을 수행합니다.콘텐츠, 디렉토리 자체가 아닌.

특별한 기능을 사용하지 않기 때문에 /bin/sh스크립트가 아닌 스크립트로 스크립트를 작성 했습니다 .bashbash

시험:

$ 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

관련 정보