用于移动一种文件类型并创建子文件夹(如果存在)的脚本?

用于移动一种文件类型并创建子文件夹(如果存在)的脚本?

我试图找到一个基本上会反复查看目录的脚本,如果该脚本找到文件.flac,它将在同一文件夹中创建一个名为 FLAC 的子文件夹,并将.flac文件仅移动到该目录中。它可能会在同一目录中找到 30 个 flac 文件,所以我不希望它在意识到该文件夹​​已经存在后崩溃,等等......

文件夹/文件布局示例:

  • 基本路径是

    /files/music
    
  • 子目录目前看起来像

    /files/music/artist
    /files/music/artist/album1
    /files/music/artist/album2
    
  • 文件显示为

    /files/music/artist/album1/01-song 1.mp3
    /files/music/artist/album1/01-song 1.flac
    /files/music/artist/album1/02-another song.mp3
    /files/music/artist/album1/02-another song.flac
    /files/music/artist/album2/01-yet another.mp3
    /files/music/artist/album2/01-yet another.flac
    
  • 所以本质上我希望它变成:

    /files/music/artist/album1/01-song1.mp3
    /files/music/artist/album1/02-another song.mp3
    /files/music/artist/album1/flac/01-song 1.flac
    /files/music/artist/album1/flac/02-another song.flac
    /files/music/artist/album2/01-yet another.mp3
    /files/music/artist/album2/flac/01-yet another.flac
    

整个想法是,在扫描大量 CD 后,我有很多包含混合版本的文件夹......因此媒体播放器最终会播放这首歌两次(首先是 mp3 版本,然后是 flac 版本)。 。

如果不存在 mp3 文件,是否可以编写一些脚本让目录保持原样? (只有 flac?)因此,如果一个文件夹只有 .flac 文件,它不会创建子文件夹......保持原样。我看到的唯一问题是它必须查找 mp3 文件,因为文件夹中可能还有其他文件(jpg 封面文件等......)

答案1

一个简单的版本,总是创建flac子目录mp3(除非它们是空的),find如果需要,使用命令执行脚本来创建子目录并将文件移动到那里:

find . -name '*.mp3' -o -name '*.flac' -exec sh -c 'mkdir -p "${0%/*}/${0##*.}" && mv "$0" "${0%/*}/${0##*.}"' {} \;

对于执行 shell 代码片段的每个文件,$0是文件的路径,${0%/*}是目录部分,${0##*.}是扩展名。

或者,在 bash 中(或 ksh93 中使用set -o globstar代替shopt -s globstar extglob,或者在 zsh 中不使用setopt ksh_glob代替),使用**图案:

shopt -s globstar extglob
for x in **/*.@(mp3|flac); do
  mkdir -p "${x%/*}/${x##*.}" && mv "$x" "${x%/*}/${x##*.}"
done

现在让我们创建一个如果所有文件都具有相同扩展名则不创建子目录的版本。在这里,对目录进行递归会更容易。这是针对 bash 的(可以适配 ksh93 或 zsh)。在每个目录中,脚本收集所有文件的列表(不包括..flac ..), all.mp3 files and allflac`files in arrays. If there is at least one flac file and at least one non-flac files, move the flac files to a子目录。mp3 文件同上。

shopt -s globstar nullglob; GLOBIGNORE=.:..
start_wd=$PWD
for dir in "$PWD"/**/*/; do
  cd "$dir"
  files=(*)
  flac_files=(*.flac)
  mp3_files=(*.mp3)
  if ((${#flac_files[@]} > 0 && ${#flac_files[@]} < ${#files[@]})); then
    mkdir flac && mv "${flac_files[@]}" flac/
  fi
  if ((${#mp3_files[@]} > 0 && ${#mp3_files[@]} < ${#files[@]})); then
    mkdir mp3 && mv "${mp3_files[@]}" mp3/
  fi
done
cd "$start_wd"

答案2

用这个:

#!/bin/bash

find /files/music/artist -type f -name '*.flac' | while IFS= read -r file; do
    dir="$(dirname "$file")"
    file="$(basename "$file")"
    shopt -s nullglob
    mp3s=( "$dir"/*.mp3 )

    if ! [[ ${#mp3s[@]} -eq 0 ]]; then
        ext="${file##*.}"
        mkdir -p "$dir/$ext" && mv -i "$dir/$file" "$dir/$ext"
    fi
done
  • find.flac将在提到的目录及其所有子目录中查找具有扩展名的文件。

  • dir将包含文件的目录名称并且file将具有文件名

  • 然后我们检查该目录是否有任何.mp3文件,如果没有则文件将保留在目录中

  • 如果该目录中有任何文件,则会创建.mp3一个扩展名为 ( ) 的目录,并且文件将移动到该目录。flac.flac

答案3

您的要求有点复杂,但这个脚本可能会有所帮助。

#!/bin/bash

run() {
        if $DRYRUN; then
                echo -n +
                printf " '%s'" "$@"
                echo
        else
                "$@"
        fi
}

DRYRUN=false
if test x"$1" = x-d; then
        DRYRUN=true
        shift
fi

for dir in "$@"; do 
        find "$dir" -type d |
        while read subdir; do
                if ls "$subdir"/*.flac >/dev/null 2>&1; then
                        if ls "$subdir"/*.mp3 >/dev/null 2>&1; then
                                run mkdir -p "$subdir"/flac
                                run mv "$subdir"/*.flac "$subdir"/flac
                        fi
                fi
        done
done

您可以通过指定 来查看将要发生的情况-d。在实际移动之前一定要仔细检查。

$ ./script.sh -d /files/music
+ 'mkdir' '-p' '/files/music/artist/album2/flac'
+ 'mv' '/files/music/artist/album2/01-yet another.flac' '/files/music/artist/album2/flac'
+ 'mkdir' '-p' '/files/music/artist/album1/flac'
+ 'mv' '/files/music/artist/album1/01-song 1.flac' '/files/music/artist/album1/02-another song.flac' '/files/music/artist/album1/flac'

相关内容