cp コマンドの出力としてファイル名のみを表示するにはどうすればよいですか?

cp コマンドの出力としてファイル名のみを表示するにはどうすればよいですか?

次のコマンドを使用して、src フォルダーから dest フォルダーにファイルをコピーしています:

cp -nv /src/* /dest/ > copy_result.txt

コピーされたファイルの結果は、以下に示すように出力ファイルに表示されます。

 « /src/test1.txt » -> « /dest/test1.txt »
 « /src/test2.txt » -> « /dest/test2.txt »

それ以外の場合は、出力ファイルに、パス全体やファイル拡張子なしでファイル名のみが含まれるようにします。次のようになります。

test1
test2

答え1

コマンドを試してください

cp -nv /src/* /dest/ | awk '{print $6}' | rev | cut -d/ -f1 | rev | cut -d. -f1 > copy_result.txt

awk6 番目のフィールドを出力します。rev文字列を反転します。cut文字列を で指定された区切り文字で分割し-d、 で指定された部分を抽出します-f

編集:
指摘されているように、これはスペースを含むファイル/ディレクトリには適していません。ただし、'-> « ' と ' »' の間の部分文字列を抽出することで対応できます。

cp -nv /src/* /dest/ | sed -e 's/.*-> « \(.*\) ».*/\1/' | rev | cut -d/ -f1 | rev | cut -d. -f1 > copy_result.txt

答え2

-vPOSIX では指定されていません。つまり、各cp実装では異なる方法で処理される可能性があります (またはまったく処理されない可能性があります)。 your がcpと言っているのに対し« foo »、 my が と言っているのです'foo'。望ましくない出力を望ましい出力に変換するコマンドを作成することは可能ですが、実装に依存しないソリューションを提示したいと思いますcp


/src/*コマンドを展開した後、cp結果のエントリを1つずつコピーします。つまり、次のように変換できますcp -n /src/* /dest/

for file in /src/*; do cp -n "$file" /dest/; done

これで、 を使って何かを行うのは簡単になりました$file。これにより、必要な出力が生成されます。

for path in /src/*; do
   file="${path##*/}"
   dst="/dest/$file"
   [ ! -e "$dst" ] && cp "$path" "$dst" && printf '%s\n' "${file%.*}"
done

(ではなく をcopy_result.txt使用するようにリダイレクトします)。done > copy_result.txtdone


cp -r -vを使用し、 の展開からのオペランドの少なくとも 1 つが/src/*ディレクトリである場合、cpはその内容をコピーして出力しますが、上記のコード ( を追加した後-r) は同じ内容をコピーしてディレクトリ自体のみを出力します。-rが矛盾を生じさせる唯一のオプションではない可能性があります。

したがって、このアプローチはcp実装から独立している必要がありますが、一部のオプションが使用されていないことに依存します。もう 1 つの欠点は、コードがcp内のすべてのオブジェクトに対して個別のプロセスを実行することです/src/。これは最適とは程遠いものです。

競合状態もあります。ファイルがと$dstの間にある場合、がその役割を果たします。 を使用すると上書きを回避できますが、ファイルは引き続き報告されます。[cpcpcp -nprintf

関連情報