複数の条件(ディレクトリ内の特定のファイルとそのディレクトリ内の特定のサブディレクトリ)を使用してfind -exec {}を最適化します。

複数の条件(ディレクトリ内の特定のファイルとそのディレクトリ内の特定のサブディレクトリ)を使用してfind -exec {}を最適化します。

私の質問は、私のNASの音楽エンコーディングとLinuxコマンドの最適化に関するものですfind

私は完璧に動作するスクリプトを書いたが、それが最善のアプローチではないと確信しています。

結論として:

1/スクリプトは、エンコードするflacを含むディレクトリを確認します。

  • .flac特定のファイルを含むすべてのディレクトリ
  • mp3/または、名前のサブディレクトリを含まないディレクトリMp3/

特定の部分について私は次のようにしました。

FILE="./DirContaininfFlacToConvertToMp3.txt"
find . -type f -iname '*.flac' -printf '%h\n' | sort -u > fic1
find . -iname 'mp3' -type d | sort | sed 's/\/Mp3//' | sed 's/\/mp3//' > fic2
comm -3 fic1 fic2 > $FILE
  • $ FILEは、これら2つの基準に一致するすべてのディレクトリを入力します。
  • fic1ファイルにはflacファイルを含むすべてのディレクトリが含まれています。
  • fic2mp3/ファイルには、mp3サブディレクトリを含むすべてのディレクトリが含まれています(sedは、commコマンドが機能するようにパスの末尾からまたはを削除するために使用されます)。Mp3/
  • comm -3私の結果を私に与える$FILE

うまく動作しますが、最善の方法ではないと確信しています。照会パラメーターを使用するか、シェルに渡して最適化します。

2/スクリプトはflacファイルをエンコードしてMp3 /サブディレクトリに移動します。

file( $FILE) が次の基準に一致するディレクトリ結果を提供する場合は、次のようにします。

  • mp3定義されたディレクトリにファイルをエンコードします。
  • Mp3(元の構造を維持)というサブディレクトリに移動しました。

この部分では、2つのループで行われました。

#1st loop to encode
IFS=$'\n'
for next in `cat $FILE`
do
  find $next -type f  -name "*.flac" -exec ffmpeg -i {} -qscale:a 2 -map_metadata 0 -id3v2_version 3 {}.mp3 \;
done

#2nd loop for moving to subdir
for next in `cat $FILE`
do
  find $next -type f -name '*.flac.mp3' -execdir mkdir -p Mp3 \; -execdir mv {} Mp3/ \;
done

また、2つのループ反復を避けることができると確信しています。

しかし、ここでは任意の目的で完全なスクリプトを見つけることができます(コーディングがあまり良くないことを知っています... :-(

フルスクリプト

#!/bin/bash
# Convert .flac en .mp3 file for Synology with ffmpeg
# usage : 1st construct list of directory to convert : run:  ./script.sh V
#         2nd verify and to convert run : nohup ./script C & 

#result of list of directories to encode
FILE="./ToConvertToMp3.txt"

# parameter validation
if [ "$#" -ne  "1" ]
  then
     echo "1 parameter required : ./script.sh (V)erify (C)onvert "
 exit 1;
fi


# generate list of directory for encoding
if [ "$1" ==  "V" ]
  then
    echo "-------- VERIFY AND CONSTRUCT LIST -------"
    #1 find dir that contains .flac file
    find . -type f -iname '*.flac' -printf '%h\n' | sort -u > fic1

    # for those directory search if there is some *mp3* subdir
    IFS=$'\n'
    for dirflac in `cat fic1`
    do
      find $dirflac -iname '*mp3*' -type d -exec dirname {} \; >> fic2
    done

    # sort and unicity
    cat fic2 | sort -u > fic3

    # final construc of the list of directory to encode
    comm -3 fic1 fic2 > $FILE
    rm -f fic1 fic2 fic3

    echo "-----DIRECTORY TO CONVERT-------"
    cat $FILE
    echo "-------------------------------------"
    exit 0
fi

# Converting .flav files from directories listed in $FILE
if [ "$1" ==  "C" ]
  then
    echo "-------- CONVERTING FLAC -------"

    if [ -e $FILE ]; then
      echo "$FILE exist : OK"
    else
      echo "$FILE does not exist Please (V)erification first"
    exit 3
    fi

  if [ -s "$FILE" ]; then
    echo "$FILE contains directories : OK"
    cat $FILE
  else
    echo "$FILE is empty , nothing to do"
    exit 2
  fi

  echo "-------- CONVERTING -------"
  IFS=$'\n'
  for next in `cat $FILE`
  do
    find $next -type f  -name "*.flac" -exec ffmpeg -i {} -qscale:a 2 -map_metadata 0 -id3v2_version 3 {}.mp3 \;
    album="$(basename $directory)-Mp3";
    echo "  Processing $directory : creating subdirectory : $album, moving files in progress"
    find $directory -type f -name '*.flac.mp3' -execdir mkdir -p "$album" \; -execdir mv {} "$album/" \;

  done
  echo "-------- END OF CONVERSION -------"

  # renaming $FILE with timestamp
  ficdate=$(date +%Y%M%d-%Hh%m);
  mv $FILE $FILE-$ficdate.done;

  exit 0
fi

echo "WARNING : 1 parameter : usage : ./script.sh (V)erification (C)onversion"

ベストアンサー1

次のことができます。

find . -type f -name '*.flac' -execdir sh -c '
  if [ ! -d mp3 ] && [ ! -d Mp3 ]; then
    for file do
      ffmpeg -i "$file" -qscale:a 2 -map_metadata 0 -id3v2_version 3 "${file%.*}.mp3"
    done
  fi' sh {} +

アイデアは、-execdir cmd {} +(一部のGNUバージョンの場合find)withが、指定されたディレクトリで一致するすべてのファイルに対して実行されることですfindcmd

私は言ったGNU Findのいくつかのバージョン以前はそれはうまくいきましたが、後でいくつかのバージョンで破損し(各ファイルが使用したかのように呼び出されますfind)、それ以降のバージョンで修正されました。cmd-execdir cmd {} \;

持っていることを確認できます。正しいバージョン:

find . -execdir echo {} +

正しいバージョンの場合はディレクトリごとに1行をインポートする必要があり、より正確なバージョンではファイルごとに1行をインポートする必要があります。

正しいバージョンがあり、ディレクトリごとに何千ものflacファイルがない場合は、両方を同時に実行できます。

find . -type f -name '*.flac' -execdir sh -c '
  if [ ! -d mp3 ] && [ ! -d Mp3 ]; then
    mkdir Mp3 || exit
    for file do
      ffmpeg -i "$file" -qscale:a 2 -map_metadata 0 -id3v2_version 3 "Mp3/${file%.*}.mp3"
    done
  fi' sh {} +

おすすめ記事