
ディレクトリには、ファイル名でソートされた多くのファイルがあります。最後の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) ~/