回答:
これは、bash / ksh93 / zsh配列を使用して簡単に実行できます。
a=(*)
cp -- "${a[@]: -4}" ~/
これは、スペース、タブ、改行、またはその他の難しい文字が含まれている場合でも、すべての非隠しファイル名に対して機能します(現在のディレクトリに少なくとも4つの非隠しファイルがある場合bash
)。
a=(*)
これにより、a
すべてのファイル名を持つ配列が作成されます。bashによって返されるファイル名はアルファベット順にソートされます。(これは、「ファイル名で並べ替えられた」という意味です。)
${a[@]: -4}
これは、配列の最後の4つの要素を返しますa
(配列にが含まれる要素が少なくとも4つある場合bash
)。
cp -- "${a[@]: -4}" ~/
これにより、最後の4つのファイル名がホームディレクトリにコピーされます。
これにより、最後の4つのファイルがホームディレクトリにのみコピーされ、同時にa_
、コピーされたファイルの名前に文字列が追加されます。
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
コマンドを実行することにより、現在どのロケールにいるかを確認できます。
あなたが使用している場合zsh
、あなたは括弧で囲むことができ()
、いわゆるのリストグロブ予選たいファイルを選択します。あなたの場合、それは
cp *(On[1,4]) ~/
ここでは、On
逆の順序でアルファベット順にファイル名をソートし、[1,4]
最初の4それらのかかります。
を使用してプレーンファイル(ディレクトリ、パイプなどを除く)のみを選択し.
、コマンドを追加--
しcp
て名前が-
適切に始まるファイルを処理することにより、これをより堅牢にすることができます。
cp -- *(.On[1,4]) ~
D
隠しファイル(ドットファイル)も考慮する場合は、修飾子を追加します。
cp -- *(D.On[1,4]) ~
*([-4,-1])
。
on
)デフォルトの動作ではありませんので、これを指定する必要、と-
下から数字カウントファイル名の前に。
これは、非常に単純な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
コピーコマンドを実行する各行をループします。
シェルの並べ替えが同意できる限り、次のことができます。
set -- /path/to/source/dir/*
[ "$#" -le 4 ] || shift "$(($#-4))"
cp "$@" /path/to/target/dir
これはbash
、提供されている-specificアレイソリューションに非常に似ていますが、POSIX互換のシェルに移植できるはずです。両方の方法に関する注意事項:
cp
引数をリードするcp --
か.
、ドットまたは/
各名前の先頭のいずれかを取得することが重要です。これを行わないと、オプションとして解釈される可能性のある最初の引数の先頭の-
ダッシュが危険にさらさcp
れ、操作が失敗したり、意図しない結果が表示される可能性があります。
set -- ./*
やのように簡単に実行できますarray=(./*)
。両方の方法を使用して、削除しようとするものと少なくとも同じ数の項目をarg配列に含めることが重要です。ここでは、数学的な拡張を行っています。shift
引数配列内の少なくとも4つの項目がある場合にのみ起こる-とだけ離れ4の余剰を作るそれらの最初の引数をシフト..
set 1 2 3 4 5
場合によってはシフトし1
ますが、set 1 2 3
場合によっては何もシフトしません。a=(1 2 3); echo "${a[@]: -4}"
空白行を印刷します。あるディレクトリから別のディレクトリにコピーする場合は、次を使用できますpax
。
set -- /path/to/source/dir/*
[ "$#" -le 4 ] || shift "$(($#-4))"
pax -rws '|.*/|new_prefix|' "$@" /path/to/target/dir
...これは、sed
コピーするときにすべてのファイル名に-style置換を適用します。
ファイルのみがあり、それらの名前に空白文字や改行文字が含まれていない(変更されていない$IFS
)か、グロブ文字(またはの一部の実装で印刷ls
できない文字)があり、先頭が.
でない場合は、これを行うことができます:
cp -- $(ls | tail -n 4) ~/
a_
4つのファイルすべてにプレフィックスをすばやく追加する方法はありますか?試しましたecho "a_$(ls | tail -n 4)"
が、最初のファイルのみを追加します。
ls
出力は、スペースだけでなくタブ、改行、または他の有効だが「難しい」文字も含むファイル名でひどく失敗するため、悪い形式と見なされます。
LC_ALL=C