このパターンで名前が付けられた何百もの画像があります。
file-001.gif
file-002.gif
file-003.gif
...
Magickを使用して、合計サイズが950kbを超えない限り、各画像セットを追加したいと思います。
その後、合計サイズが950kb未満の場合は、次のバッチを処理します。
これはシェルスクリプトで達成できますか?
答え1
まあ、私はこれが私が見たものの最悪の1行だと確信していますが、それがうまくいくと思います。緩くベースhttps://askubuntu.com/questions/878948/how-do-i-generate-a-running-cumulative-total-of-the-numbers-in-a-text-file
sed $(echo 3+`ls -la | tee out/filesWithSizes.txt | awk '{print $5}' | awk '{total += $0; $0 = total}1' | sed 's/$/ < 950000/' | bc | grep -o '1' | wc -l`|bc )q out/filesWithSizes.txt | tail -n +4
この狂気を説明しましょう。
ls -la
すべてのファイルとサイズを取得するために使用されます。
tee
後で参照できるように、その情報を保存してパイプラインに保存するために使用されます。
5列印刷用awk
(例:サイズ)
moreを使用してawk
累積合計を作成し、各デザインが整列することを保証します(後で重要になります)。
sed
行末を置き換えるために使用されるので、デフォルトで< 950000
文字列を追加します。
bc
これらの式を評価し、ブール値(0または1など)に変換するために使用されます。
grep -o
1を含む行のみを印刷するために使用されます。
累積合計は設計によってソートされているため、出力を計算し、一緒に貼り付けることができるファイルの数を順番に知ることができます。
この部分はで終わりましたwc -l
。最初はaフラグなしでは動作できなかったので、3 +ファイルリスト出力の停止点を取得するために計算したls
ばかりの数値をエコーしました。bc
次に、sed
コマンド置換を使用して、以前にechoを使用して計算した行数の後に保存されたファイルのリストの内容とサイズの出力を停止します。
tail
最後に、そのファイルのヘッダーではなく、最初の行から出力を開始するために使用されます。
これにより、接続できるすべてのファイルのリストが表示されます。処理されたすべてのファイルを移動し、ディレクトリにファイルがなくなるまで巨大なオネライナを再実行し続けます。
答え2
一括追加する必要がある画像が950kB未満のオブジェクトで終わる場合、単一の画像ファイルは同じサイズの区切りを超えることはできません。
最初のステップ:そのファイルとそのサイズの両方をバイト単位でリストします。
$ find -L /path/to/directory -maxdepth 1 -type f -name "*.gif" -size -950k \
-exec sh -c '\ls -Lgo "$1" | tr -s " " | cut "-d " -f3,7-' sh {} \;
これにより、見つかったすべてのファイルの名前とそのサイズが、見つかった順序で一度に1行ずつ画面に印刷されます。主な兆候find
は次のとおりです。
-L
:シンボリックリンクに従い、リンク自体ではなくリンク先に関する情報を表示します。これを望まない場合はを-H
使用してください。-maxdepth 1
:ドロップできる検索を実行します。1
レベル、落ちることから/path/to/directory
。必要に応じて番号を変更します。詳細についてはを参照してくださいman find
。
少なくともbash
5.0の実装では、find
キロバイト(kiB)単位で動作するようです。つまり、上記の場合は、950×1024バイト以下のサイズのファイルを探します。カットオフサイズを950KB(950000B)に設定しても問題ありません。ただ使用してください-size 927730c
。 Debianディストリビューションでは、この問題は2016年に解決されたように見えるため、引き続き使用できます-size 950k
。
「サイズ」あいまいな属性かもしれません。 OPにはより多くの情報が不足しているため、次のものを使用できるという事実も含まれていました。割り当てられた合計ブロックサイズ見つかった各ファイルについて。これがあなたが望むか必要なものなら、次のことを行います。
$ find -L /path/to/directory -maxdepth 1 -type f -name "*.gif" -size -950k \
-exec sh -c '\ls -Ls -C1 "$1"' sh {} \;
ここで得られるサイズの数値は、記憶媒体のブロックサイズに依存する。
ステップ2magick
:シェルスクリプトを使用して前のbatch_append.sh
出力を一度に処理します。画像ファイルはリストされた順序で添付されますが、結果の重量は950 kBを超えることはできません。このコマンドの出力は、find
次のように配列を埋めるために使用されます。
$ cat batch_append.sh
#!/usr/bin/bash
sdir=/path/to/directory
size=0
nas_idx=0 # next append start (nas) index (idx)
cnt=0
declare -a b
IFS=$'\n' read -d '' -a a < <(find -L "$sdir" -maxdepth 1 -type f -name "*.gif" -size -950k -exec sh -c '\ls -Lgo "$1" | tr -s " " | cut "-d " -f3,7-' sh {} \; 2>/dev/null)
num=${#a[@]}
for (( i=0; i<num; i++ )); do
(( size+=$(echo "${a[$i]}" | cut "-d " -f1) ))
if [ "$size" -gt 950000 ] ; then
(( size-=$(echo "${a[$i]}" | cut "-d " -f1) ))
(( i-=1 ))
#echo "$size" for files from "$(( nas_idx+1 ))" to "$(( i+1 ))" # testing
#echo "${b[@]}" # testing
magick "${b[@]}" append appended_$(( nas_idx+1 ))_$(( i+1 )).gif
nas_idx=$(( i+1 ))
size=0 # reset 'size' variable to start new append batch
cnt=0
unset b
else
b[cnt]=$(echo "${a[$i]}" | cut "-d " -f2-)
(( cnt++ ))
fi
if (( i==num-1 )); then
# last append batch
#echo "$size" for files from "$(( nas_idx+1 ))" to "$(( i+1 ))" # testing
#echo "${b[@]}" # testing
magick "${b[@]}" append appended_$(( nas_idx+1 ))_$(( i+1 )).gif
unset b
fi
done
printf '\n %d files were processed.\n' "$num"
exit(0)
結論:
- 実行する前にスクリプトを実行可能にしてください。
chmod ug+x batch_append.sh
- スクリプトを一度だけ実行するだけです。
- スクリプトはまだ渡されていません
magick
。 - 実稼働環境では、含める必要のある問題がたくさんあります。
- ホストにマルチコアがあり、多数のファイルを処理する必要がある場合は、並列実行をスケジュールしてスクリプトを改善できます。
- ファイルは到着するとすぐにバッチ処理されます。つまり、
find
cmdがファイルを計算するときです。これは、検索フラグの数とそれを連続的にソートする方法によって異なりますfind
。