我试图找到一个基本上会反复查看目录的脚本,如果该脚本找到文件.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 all
flac`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'