디렉토리가 항상 동일하지 않은 경우 디렉토리의 각 디렉토리 이름에서 변수를 생성하는 루프를 생성할 수 있습니까?

디렉토리가 항상 동일하지 않은 경우 디렉토리의 각 디렉토리 이름에서 변수를 생성하는 루프를 생성할 수 있습니까?

특정 디렉터리의 모든 하위 폴더를 가져오고, 다른 디렉터리에 하위 폴더를 생성한 다음 새로 생성된 하위 폴더에 하위 폴더를 생성하는 Synology DS 1019+에서 실행되는 스크립트를 작성하고 있습니다. 다른 위치에 있는 모든 .mkv 파일에 대한 하드 링크 . 그러나 하위 폴더가 이미 두 번째 위치에 있는 경우 하드 링크를 생성하고 싶습니다.

내 파일의 특성으로 인해 해당 폴더 내의 폴더 구조와 파일은 이 스크립트가 사용될 각 인스턴스마다 다릅니다. 각 루프가 위치 A의 다음 폴더를 가져오고 각 하위 폴더에 대해(해당 하위 폴더의 파일에 대해) mkdir 및 하드링크 작업을 수행하도록 이 스크립트 루프를 만드는 방법이 있습니까?

이것이 내가 현재 가지고 있는 것입니다:

#! /bin/bash

echo "Enter Movie Collection:"
read MOVIE_DIR
echo "Enter Bonus Feature Disc: "
read BONUS_DIR

cd "/volume1/Plex/Movies/$MOVIE_DIR/"

for dir in */.; do

    if [[ ! -e "$dir"/*/ ]]; then
        mkdir "$dir"/*/
    fi

    if [[ ! -d "$dir"/*/ ]]; then
        ln /volume1/Plex/"Bonus Feature Discs"/$BONUS_DIR/*/*.mkv -t ./"$dir"/*/.
    fi
done

저는 루프, 특히 중첩 루프에 대한 경험이 전혀 없기 때문에 이 문제를 어디서부터 시작해야 할지 모르겠습니다. 현재 위치 A의 폴더가 아직 존재하지 않는 경우 위치 B로 복사하거나 위치 A의 폴더 내의 파일을 하드 링크하는 대신 위치 B의 폴더를 위치 B의 홈 디렉터리(예: 내 테스트에서는 "TEST 1"이 하드 링크 TEST.mkv를 포함하는 "featurette" 폴더를 가져오는 대신 "TEST 1"에 빈 정크 데이터 폴더를 가져옵니다.

기본 이름과 디렉터리 이름을 사용해 보았지만 디렉터리의 각 폴더를 반복하도록 루프를 만드는 방법을 찾지 못했습니다. 나도 사용해봤는데cd /the/directory/path/ "${PWD##*/}"

편집: 이 글을 게시한 지 몇 시간 만에 해결책을 찾았습니다. 위의 코드는 불특정 영역이 너무 많아 아무 일도 일어나지 않기 때문에 전혀 논리적으로 이해되지 않습니다. 결국 처음부터 다시 시작해야 했어요. 이것은 내가 해야 할 일을 정확히 수행하는 코드입니다. 이 작업을 수행하는 가장 우아한 방법은 아닐 수도 있지만, 제가 실행한 테스트에 따르면 충분히 잘 작동합니다.

#! /bin/bash

#Ask the user to input the directories of both the bonus disc's files and where the movies are located that the bonus disc's contents will be needed.
echo "Enter the name of the Movie Collection and press [ENTER]: "
read MOVIE_DIR
echo "Enter the name of the Bonus Feature Disc and press [ENTER]: "
read BONUS_DIR


#This goes to the location of the bonus disc specified by the end user. I believe this part is necessary for creating the text document below, but it might not be.
cd "/volume1/Plex/Bonus Feature Discs/$BONUS_DIR/" || return

#This creates a text document that has each directory within the specified Bonus Disc directory as a separate line  
    ls -d -- */ >> /volume1/Plex/"Bonus Feature Discs"/output.txt
    echo ls  -d -- */


#This goes to the movie directory specified by the end user. This cd is definitely required
cd "/volume1/Plex/Movies/$MOVIE_DIR/" || return


#the for loop loops through every movie that resides in the movie collection folder
 for dir in *; do

    #this while loop reads the text document and will use each line from the document as a variable.
    while IFS=' ' read -r line; do
        name="$line"

        #A directory with the name of the line of the text document will be created in each movies directory only if it doesn't already exist
        mkdir -p "$dir/$name"

        #this will create the hard links to every single video that resides in the folders within the bonus features disc into the corresponding folders for each movie
        if [[ ! -e "/volume1/Plex/Movies/$MOVIE_DIR/$name" ]]; then 
            ln "/volume1/Plex/Bonus Feature Discs/$BONUS_DIR/$name"*.mkv -t ./"$dir/$name"
        fi

    done < "/volume1/Plex/Bonus Feature Discs/output.txt"
 done

echo "Linking Completed"
echo $dir

#finally, once all the work is complete, the script will delete the text document that is no longer needed
rm "/volume1/Plex/Bonus Feature Discs/output.txt"

답변1

를 사용하고 모든 디렉토리 생성을 포함하여(파일이 없는 경우에도 ) 디렉토리 내부 또는 아래의 모든 파일을 디렉토리에 하드 링크한다고 rsync가정합니다 ..mkvsourcetarget.mkv

rsync --archive --link-dest="$PWD/source" \
    --include='*/' \
    --include='*.mkv' \
    --exclude='*' \
    source/ target

--archive( ) 옵션은 파일 메타데이터를 -a보존 rsync하고 디렉터리의 재귀 복사를 트리거합니다. 이 옵션은 기존 파일을 하드 링크할 수 있는 디렉터리를 --link-dest제공합니다 . 이 옵션은 디렉터리와 파일을 선택하는 반면, 마지막 옵션은 선택되지 않은 항목을 무시합니다 .rsynctarget--include.mkv--exclude--include

에서 생성될 수 있는 빈 디렉터리를 삭제하려면 다음 명령을 target사용할 수 있습니다 .find

find target -type d -empty -delete

... 테스트와 작업을 find구현한다고 가정합니다 .-empty-delete

예:

source
|-- dir1
|   |-- file1.mkv
|   |-- file1.txt
|   |-- file2.mkv
|   `-- file2.txt
|-- dir2
|   |-- file1.mkv
|   |-- file1.txt
|   |-- file2.mkv
|   `-- file2.txt
|-- dir3
|   |-- file1.mkv
|   |-- file1.txt
|   |-- file2.mkv
|   `-- file2.txt
`-- dir4
    `-- file1.doc

위의 명령을 rsync실행하면 target다음과 같이 됩니다.

target
|-- dir1
|   |-- file1.mkv
|   `-- file2.mkv
|-- dir2
|   |-- file1.mkv
|   `-- file2.mkv
|-- dir3
|   |-- file1.mkv
|   `-- file2.mkv
`-- dir4

파일이 하드 링크되어 있음을 보여줍니다(동일한 inode 번호, 링크 수 2).

$ ls -l -i source/dir1/file1.mkv target/dir1/file1.mkv
3118217 -rw-r--r--  2 kk  kk  0 Apr 10 17:03 source/dir1/file1.mkv
3118217 -rw-r--r--  2 kk  kk  0 Apr 10 17:03 target/dir1/file1.mkv

빈 디렉터리를 삭제합니다.

$ find target -type d -empty -delete
$ tree target
target
|-- dir1
|   |-- file1.mkv
|   `-- file2.mkv
|-- dir2
|   |-- file1.mkv
|   `-- file2.mkv
`-- dir3
    |-- file1.mkv
    `-- file2.mkv

답변2

dirA어떻게든 두 변수와 dirB(설명의 "위치 A" 및 "두 번째 위치") 에 값을 할당 한다고 가정합니다 .

당신은 그것을 반복합니다 dirA.

파일이 dirA디렉터리일 때마다 동일한 이름을 가진 다른 디렉터리를 만듭니다 dirB. 이 --parent스위치는 새 디렉터리가 이미 존재하는 경우 오류가 발생하는 것을 방지하므로 mkdir새 디렉터리가 있는지 확인할 필요가 없습니다.

내부적으로 if.mkv 파일이 있는지 확인하고 없으면 해당 디렉터리를 건너뜁니다.

스크립트는 단일 디렉터리 수준에서 작동합니다. 디렉터리 내에 디렉터리가 있으면 해당 디렉터리는 확인되지 않습니다.

    #! /bin/bash

    dirA=...
    dirB=...

    cd "$dirA"

    for dir in *; do
      if [ -d "$dir" ]; then
         names=$(find "$dir" -maxdepth 1 -name '*.mkv')
         if [ "$names" ]; then
           mkdir --parent "$dirB/$dir"
           ln "$dir"/*.mkv "$dirB/$dir"
         fi
      fi
    done

관련 정보