ディレクトリの最後のN個のファイルを取得するには?

ディレクトリの最後のN個のファイルを取得するには?

ディレクトリには、ファイル名でソートされた多くのファイルがあります。最後のN個(N = 4と仮定)ファイルを私のホームディレクトリにコピーしたいと思います。どうすればいいですか?

cp ./<the final 4 files> ~/

答え1

これはbash / ksh93 / zsh配列を使用して簡単に行うことができます。

a=(*)
cp -- "${a[@]: -4}" ~/

これは、空白、タブ、改行、またはその他の難しい文字が含まれている場合でも、隠されていないすべてのファイル名に対して機能します(現在のディレクトリに隠されていないファイルが4つ以上あると仮定bash)。

どのように動作しますか?

  • a=(*)

    aこれにより、すべてのファイル名を含む配列が作成されます。 Bashから返されたファイル名はアルファベット順にソートされます。 (私の考えでは、これがまさにあなたの意味であるようです。「ファイル名で並べ替えてください。」)

  • ${a[@]: -4}

    これにより、配列の最後の4つの要素が返されますa(配列にが含まれる要素が4つ以上含まれている場合bash)。

  • cp -- "${a[@]: -4}" ~/

    これにより、最後の4つのファイル名がホームディレクトリにコピーされます。

同時にコピーして名前を変更する

a_これにより、最後の4つのファイルのみがホームディレクトリにコピーされ、コピーされたファイル名の前に文字列が追加されます。

a=(*)
for fname in "${a[@]: -4}"; do cp -- "$fname" ~/a_"$fname"; done

別のディレクトリからコピーして名前を変更します。

a=(./some_dir/*)代わりに使用すると、a=(*)ファイル名にディレクトリが追加されるという問題が発生します。 1つの解決策は次のとおりです。

a=(./some_dir/*) 
for f in "${a[@]: -4}"; do cp "$f"  ~/a_"${f##*/}"; done

別の解決策は、サブシェルを使用してcdサブシェルのディレクトリにアクセスすることです。

(cd ./some_dir && a=(*) && for f in "${a[@]: -4}"; do cp -- "$f" ~/a_"$f"; done) 

サブシェルが完了すると、シェルは元のディレクトリに戻ります。

順序が一貫していることを確認してください。

質問は、「ファイル名でソートされた」ファイルについて尋ねます。 Olivier Dulacは、彼のコメントで、この順序は地域によって異なります。システム設定に関係なく、固定結果が重要な場合は、配列を定義するaときにロケールを明示的に指定することをお勧めします。たとえば、

LC_ALL=C a=(*)

このコマンドを実行すると、現在どのロケールにあるかを確認できますlocale

答え2

以下を使用する場合は、いわゆるリストを括弧で囲むzshことができます。()グローバル予選必要なファイルを選択してください。あなたの場合

cp *(On[1,4]) ~/

ここでは、Onファイル名はアルファベットの逆順でソートされ、[1,4]最初の4つのみが使用されます。

名前が正しいファイルで始まるファイルを正しく処理するには、コマンドを使用して通常のファイル(ディレクトリ、パイプなどを除く)のみを選択し、コマンドに追加すると.より強力になります。--cp-

cp -- *(.On[1,4]) ~

D隠しファイル(ドットファイル)も考慮するには、修飾子を追加してください。

cp -- *(D.On[1,4]) ~

答え3

これは非常に単純なbashコマンドを使用するソリューションです。

find . -maxdepth 1 -type f | sort | tail -n 4 | while read -r file; do cp "$file" ~/; done

説明する:

find . -maxdepth 1 -type f

現在のディレクトリですべてのファイルを見つけます。

sort

アルファベット順に並べ替えます。

tail -n 4

最後の4行だけが表示されます。

while read -r file; do cp "$file" ~/; done

コピーコマンドの各行を繰り返します。

答え4

ファイルのみがあり、ファイル名に空白や改行文字(変更されていない場合$IFS)、グローバル文字(または一部の実装では印刷できない一部の文字ls)が含まれておらず、次から始まらない場合.

cp -- $(ls | tail -n 4) ~/

関連情報