私はbashスクリプトを書いていますが、現在のディレクトリに最新の10個の画像ファイル(新しいものから古いものへ)を含む配列を作成する必要があります。
「画像ファイル」は、_.jpg
_や_.png
_などの特定の拡張子を持つファイルだと思います。サポートする必要がある特定の画像タイプはいくつかありますが、これを"\.(jpg|png)$"
のような1つの正規表現で表現することもできます。
私の問題は、私がこれを例えばでやろうとするとです。 $list=(ls -1t *.jpg *.png | head -10)
結果のファイルのリストは、各ファイル名が配列内の個別の要素ではなく、どういうわけか1つの要素になります。
$list=(find -E . -iregex ".*(jpg|png)" -maxdepth 1 -type f | head -10)
を使おうとすると、リストを日付/時刻で並べ替えてファイル名だけを保持する方法がわかりません。また、findはすべてのファイルの前に_./
_を配置しているようですが、sed
でそれを取り除くことができます。また、find
でも、リスト全体が_$list
_配列の1つのエントリになるという問題があります。
正しい構文は次のとおりです。
list=($(ls -t *.jpg *.png | head -10))
echo First element: ${list[0]}
echo Last element: ${list[9]}
ただし、このソリューションでは、スペース文字(または一般的な空白)を含むファイル名に問題があります。
bash
≥4の場合:
コマンドの出力を1行ずつ配列に読み込むには、readarray
を使用する必要があります。
readarray files < <(ls -1t *.jpg *.png | head -10)
...またはmapfile
:
mapfile -t files < <(ls -1t *.jpg *.png | head -10)
さもないと:
files=()
while IFS= read -r f; do
files+=( "$f" )
done < <(ls -1t *.jpg *.png | head -10)
参照 。
しかし、ファイル名には改行を含めることができるため、ファイル名を読み取るには、代わりにfind
を使用して\0
区切り文字を使用する必要がありますls -1
区切り文字を使用する\n
の:
files=()
while IFS= read -r -d $'\0' f; do
files+=("$f")
done < <(
find . -maxdepth 1 -type f \
-regextype posix-extended -iregex ".*\.(jpg|png)$" \
-printf '%T@\t%P\0' \
| sort -nrz \
| head -z -n 10 \
| cut -z -f2-
)
Zshがオプションの場合、それはかなり単純です。
_set -o nocaseglob
array=( *.(png|jpg)(Om[-10,-1]) )
_
_set -o nocaseglob
_を使用すると、より単純な_png|jpg
_を、PNG
やJpG
などのケースのバリエーションに一致させることができます。
次のステートメントは、非常に特定のファイル名生成(glob)の結果を配列に割り当てます。左から右へ:
*.(png|jpg)
-大文字と小文字を区別するオプションを有効にした場合、_.jpg
_または_.png
_で終わるファイル名のリストに展開されます(Om ...)
_-変更時間(古いものから新しいものへ)でファイルをソート(O
rder)するように指示するzsh「グロブ修飾子」[-10,-1]
_-最後に10個の要素(最新の10個のファイル)を取得するzsh配列スプライス構文を解析できるようになると、グロブ/ファイル名の生成によってファイル名が処理されるため、zshを使用すると、このような状況の処理が簡単になります。ls
の解析について心配する必要はありません。たとえば、 その他の回答 で生成した「楽しい」ファイル名を使用すると、結果は次のようになります。
_$ print -l $array
4521.png
a?b.jpg
$( echo boom ).jpg
a*b.jpg
[x].jpg
X▒Y.jpg
single'quote.jpg
backslash.jpg
②.jpg
*.jpg
_
(一部のファイルのタイムスタンプが同じであるため、結果はシーケンスでわずかに異なります)。