當目錄並不總是相同時,是否可以建立一個循環,從目錄中的每個目錄名稱建立一個變數?

當目錄並不總是相同時,是否可以建立一個循環,從目錄中的每個目錄名稱建立一個變數?

我正在編寫一個在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 的主目錄(例如,在在我的測試中,我只是在“TEST 1”中獲取空的垃圾資料資料夾,而不是“TEST 1”獲取其中包含硬連結TEST.mkv 的“featurette”資料夾。

我嘗試使用基名和目錄名,但我還沒有找到一種方法讓它循環,以便它循環遍歷目錄中的每個資料夾。我也嘗試過使用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,並假設您希望將目錄.mkv中或source目錄下的所有檔案硬連結到目錄中target,包括建立所有目錄(即使它們沒有.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

相關內容