ディレクトリナビゲーション、ツリー比較、片側に見つからないファイルのみを削除

ディレクトリナビゲーション、ツリー比較、片側に見つからないファイルのみを削除

.mp3そのフォルダに一致するファイルがないディレクトリ階層のファイルと、.jpg .pngファイルにそのファイルがない階層の他のファイルを削除する方法を見つけようとしています。 )/out/.flac/in//out/in/'. The only extension to mutate here are those two but there will be other files (like,

#!/bin/bash
find /in>/tmp/in.txt
sed 's/.flac/.mp3/g; s+/in+/out+g' /tmp/in.txt>/tmp/inx.txt
find /out>/tmp/out.txt
grep -vxF -f /tmp/inx.txt /tmp/out.txt>/tmp/clean.txt
while read line; do rm "$line"; done < /tmp/clean.txt

最後に、空のフォルダをクリーンアップします。この行は、空のディレクトリを削除するいくつかの「トリック」です。上記の「rm」を使って上記のファイルやフォルダを削除することができれば良いでしょうが、これは危険ですか?

find /out/. -depth -type d -exec rmdir {} + 2>/dev/null

これまで、私は最初の2つが次のようにマージできることを発見しました。

find /in | sed 's/.flac/.mp3/g; s+/in+/out+g'>/config/inx.txt

私は以下を使用しようとしています:

grep -vxF -f /tmp/inx.txt `find /out`>/tmp/clean.txt

しかし、エラーが発生します。パラメータリストが長すぎます。

これらすべてを一つにまとめて処理時間を節約する方法はありますか?これまでは完了するのに約10分かかります。


次の試みは、単一引用符付きのファイル/フォルダを除いて機能します(IFSは少なくともスペースを処理できます)。

#!/bin/bash
IFS=$'\n'; set -f
for mp in $(find /out)
do
    mf="${mp%/out/}/in/"  # Change /out/ to /in/
    ff="${mf%mp3}flac"    # Convert mp3 filename to flac
    [[ ! -f "$ff" ]] && echo rm "$mp"
done
unset IFS; set +f

大丈夫。私の考えではこれです。この時点で音楽ファイル以上のものを確認することを反映するように元の質問を編集しました。

#!/bin/bash
find /out -type f -name '*' -exec bash -c '
    for mp in "$0" "$@";
    do
        mf="${mp#/out/}";               # Strip /out/ base prefix leaving relative pathname
        if [ "${mf##*.}" = "mp3" ]; then
                mf="${mf%.mp3}.flac";   # convert filename to flac if it was mp3
        fi;
        [[ ! -f "/in/$mf" ]] && echo rm "$mp";
    done
' {} +

Bashの略語がどのように機能するかを理解してください。

#!/bin/bash
find /out -type f -exec bash -c '
    for mp in "$0" "$@";
    do
        mf="${mp#/out/}";       # Strip /out/ base prefix leaving relative pathname
        [[ "${mf##*.}" == "mp3" ]] && mf="${mf%.mp3}.flac";     # convert filename to flac if it was mp3
        [[ ! -f "/in/$mf" ]] && echo rm "$mp";      # remove /out/ file if no match
    done
' {} +

答え1

grepまたはを使用する必要はありませんsed。プロセスの性質は、次のように単一のディレクトリに対して表示できます。

#!/bin/bash
for op in /out/*.mp3
do
    mp="${mp##/out/}"       # Strip /out/ base prefix leaving relative pathname
    fp="${mf%.mp3}.flac"    # Convert mp3 name to flac
    [[ ! -f "/in/$fp" ]] && echo rm "$op"
done

ディレクトリツリーにはこれが必要なので、各ディレクトリに順番に適用する必要があります。

find /out -type f -name '*.mp3' -exec bash -c '
    for mp in "$0" "$@";
    do
        mp="${mp#/out/}";
        fp="${mf%.mp3}.flac";
        [[ ! -f "/in/$fp" ]] && echo rm "$op";
    done
' {} +

findサポートされていない場合は、どちらの場合も正しいファイルを削除し、満足している場合は削除-exec ... +します+';'echo

関連情報