私のフォルダには名前にスペースを含む11個のファイルがありますが、最新の10個のファイルをコピーしたいと思います。以前は、ls -t | head -n 10
最新の10個のファイルしかインポートできませんでした。 cpステートメントで式を使用しようとすると、名前にスペースが含まれているため、ファイルが見つからないというエラーが発生します。
たとえば、次のようにcp: cannot stat ‘10’: No such file or directory
なります。10 abc.pdf
CPドア:cp $(ls -t | head -n 10) ~/...
どのように動作させることができますか?
ベストアンサー1
Bashを使用していて100%安全な方法が必要な場合(ファイル名に注意する必要がある難しい方法を学んだので、あなたも欲しいと思います)、次のことができます。
shopt -s nullglob
while IFS= read -r file; do
file=${file#* }
eval "file=$file"
cp "$file" Destination
done < <(
for f in *; do
printf '%s %q\n' "$(date -r "$f" +'%s')" "$f"
done | sort -rn | head -n10
)
そのうちのいくつかを見てみましょう。
for f in *; do
printf '%s %q\n' "$(date -r "$f" +'%s')" "$f"
done
これは、フォームの標準出力用語で印刷されます。
Timestamp Filename
ここで、タイムスタンプはエポック(-r
オプションで得られたdate
)以降の変更日(秒)で、ファイル名は引用されたファイル名のバージョンです。シェル入力で再利用可能(フォーマット指定子を参照してくださいhelp printf
)%q
。次に、行を数字順、逆順に並べ替え、sort
最初の10行だけを保持します。
while
次にループに供給します。タイムスタンプは割り当てfile=${file# *}
(最初のスペースの前のすべてのエントリを削除)として削除され、明らかに危険な行にはeval "file=$file"
エスケープ文字が削除され、printf %q
最後にファイルを安全にコピーできます。
おそらく最善のアプローチや実装ではないかもしれませんが、可能なすべてのファイル名に対して100%の安全性が保証され、作業が完了します。ただし、これは通常のファイル、ディレクトリなどを同じように扱います。通常のファイルに制限するには、[[ -f $f ]] || continue
このfor f in *; do
行の後に追加してください。また、隠しファイルは考慮しません。ファイルを隠すには(もちろんそうでは.
ありません..
)shopt -s dotglob
。
もう1つの100%Bashソリューションは、Bashを直接使用してファイルをソートすることです。クイックソートの使用方法は次のとおりです。
quicksort() {
# quicksorts the filenames passed as positional parameters
# wrt modification time, newest first
# return array is quicksort_ret
if (($#==0)); then
quicksort_ret=()
return
fi
local pivot=$1 oldest=() newest=() f
shift
for f; do
if [[ $f -nt $pivot ]]; then
newest+=( "$f" )
else
oldest+=( "$f" )
fi
done
quicksort "${oldest[@]}"
oldest=( "${quicksort_ret[@]}" )
quicksort "${newest[@]}"
quicksort_ret+=( "$pivot" "${oldest[@]}" )
}
その後、それらをソートして上位10個を保持してからターゲットにコピーします。
$ shopt -s nullglob
$ quicksort *
$ cp -- "${quicksort_ret[@]:0:10}" Destination
以前の方法と同様に、通常のファイル、ディレクトリなどを同じように処理し、隠しファイルをスキップします。
別のアプローチ:およびパラメータがls
ある場合は、次のものを使用できます。i
q
ls -tiq | head -n10 | cut -d ' ' -f1 | xargs -I X find -inum X -exec cp {} Destination \; -quit
これにより、ファイルの inode が表示され、find
その inode が参照するファイルからコマンドを実行できます。
繰り返しますが、これは通常のファイルだけでなくディレクトリなども処理します。ls
出力形式に依存しすぎるので、これはあまり好きではありません...