디렉터리가 항상 동일하지 않을 때 디렉터리 내의 각 디렉터리 이름에서 변수를 생성하는 루프를 만드는 것이 가능합니까?

디렉터리가 항상 동일하지 않을 때 디렉터리 내의 각 디렉터리 이름에서 변수를 생성하는 루프를 만드는 것이 가능합니까?

저는 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의 폴더 내의 파일이 하드링크되는 대신에 "_2X68P~X"라는 이름의 빈 폴더가 생성됩니다. 위치 B의 기본 디렉터리(예를 들어 내 테스트에서는 "TEST 1"이 하드링크된 TEST.mkv가 있는 "featurette" 폴더를 가져오는 대신 "TEST 1" 내에 비어 있는 가비지 데이터 폴더를 가져옵니다.

나는 dirname뿐만 아니라 basename도 사용하려고 시도했지만 디렉터리 내의 각 폴더를 순환하도록 반복하는 방법을 아직 찾지 못했습니다. 나는 또한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옵션은 rsync기존 파일을 에서 하드 링크할 수 있는 디렉토리를 제공합니다 target. 옵션 --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

관련 정보