Linux検索機能で見つけたファイルをコピーして名前を変更するには?

Linux検索機能で見つけたファイルをコピーして名前を変更するには?

487個のフォルダがあるというフォルダがあります/home/user/temps。各フォルダにはThumb.pngというファイルがあります。

Thumb.pngという名前のすべてのファイルを別のフォルダにコピーし、元のフォルダに応じて名前を変更したいと思います。

答え1

ここにあります:

for file in /home/user/temps/*/thumb.png; do new_file=${file/temps/new_folder}; cp "$file" "${new_file/\/thumb/}"; done;

編集する:

ところで、一般的な通念はこうするのがfind悪い考えだということです。単にシェル拡張を使用する方がより安定しています。また、これは仮説ですbashが、安全な仮定だと思います:)

編集2:

明確にするために分析します。

# shell-expansion to loop specified files
for file in /home/user/temps/*/thumb.png; do

    # replace 'temps' with 'new_folder' in the path
    # '/home/temps/abc/thumb.png' becomes '/home/new_folder/abc/thumb.png'
    new_file=${file/temps/new_folder};

    # drop '/thumb' from the path
    # '/home/new_folder/abc/thumb.png' becomes '/home/new_folder/abc.png'
    cp "$file" "${new_file/\/thumb/}";
done;

${var/Pattern/Replacement}詳細な工事情報をご確認いただけます。ここ

この行の引用符は、cpファイル名のスペース、改行などを処理するために重要です。

答え2

このソリューションは、サブディレクトリとサブディレクトリのファイルを「フラット化」して、両方とも1つの大きなディレクトリに存在するようにします。新しいファイル名は元のパスを反映します。たとえばにtemps/dir/subdir/thumb.pngなりますnewdir/temps_dir_subdir_thumb.png

find temps/ -name "thumb.png" |
  while IFS= read -r f do
    cp -v "$f" "newdir/${f//\//_}"
  done

ディレクトリtempsnewdir存在する必要があります。そして、tempsコマンドはおよびの親ディレクトリで実行する必要がありますnewdir

このコマンドは1行で完了することもできます。

find temps/ -name "thumb.png" | while IFS= read -r f; do cp -v "$f" "newdir/${f//\//_}"; done

;改行文字を含むセミコロン()に注意してください。


出力例

$ find temps/ -name "thumb.png" | while IFS= read -r f; do cp -v "$f" "newdir/${f//\//_}"; done
`temps/thumb.png' -> `newdir/temps_thumb.png'
`temps/dir3/thumb.png' -> `newdir/temps_dir3_thumb.png'
`temps/dir3/dir31/thumb.png' -> `newdir/temps_dir3_dir31_thumb.png'
`temps/dir3/dir32/thumb.png' -> `newdir/temps_dir3_dir32_thumb.png'
`temps/dir1/thumb.png' -> `newdir/temps_dir1_thumb.png'
`temps/dir2/thumb.png' -> `newdir/temps_dir2_thumb.png'
`temps/dir2/dir21/thumb.png' -> `newdir/temps_dir2_dir21_thumb.png'

わからない場合は、追加してecho実行するcp内容を確認してください。

find  temps/ -name "thumb.png" | while IFS= read -r f; do echo cp -v "$f" "newdir/${f//\//_}"; done

説明する

これは次の方法で行うことができます。パラメータ拡張${f//\//_}。変数の内容f(パスとファイル名を含む)を取得し、各項目/_

これは愚かなテキスト検索と置換です。 2つの異なるファイルが同じ名前で終わる場合は、ファイルの1つが上書きされます。

たとえば、2つのファイルtemps/dir/thumb.pngtemps/dir_thumb.png。どちらのファイルも名前がtemps_dir_thumb.png. に変更されるため、1 つのファイルが失われます。失われるファイルは、findディスクに見つかった順序によって異なります。

義務的な賢明な警告:ファイル名に改行文字が含まれていると、このコマンドは激しくクラッシュします。

答え3

oneliner コマンドでファイルを検索、コピー、名前を変更できます。-sh 実行:

find /home/user/temps -name thumb.png \
-exec sh -c 'cp "{}" "$(basename "$(dirname "{}")")_$(basename "{}")"' \;

(追加の内容は"コピーされたファイルを空白として扱うことです。)

オプション2- with xargs(実行前に各コマンドを印刷できます):

find /home/user/temps -name thumb.png \
| xargs -I {} --verbose sh -c 'cp "{}" "$(basename "$(dirname "{}")")_$(basename "{}")"'

sh -c cp "temps/thumb.png" "$(デフォルト名 "$(dirname "temps/thumb.png")")_$(デフォルト名 "temps/thumb.png")"

sh -c cp "temps/dir one/thumb.png" "$(basename "$(dirname "temps/dir one/thumb.png")")_$(basename "temps/dir one/thumb.png") 」

sh -c cp "temps/dir two/thumb.png" "$(basename "$(dirname "temps/dir two/thumb.png")")_$(basename "temps/dir two/thumb.png") 」

答え4

この試み

mkdir /home/user/thumbs
targDir=/home/user/thumbs

cd /home/user/temps

find . -type d | 
 while IFS="" read -r dir ; do
   if [[ -f "${dir}"/thumb.png ]] ; then
     echo mv -i "${dir}/thumb.png" "${targDir}/${dir}_thumb.png"
   fi
done

編集する

ディレクトリ名にスペース文字が含まれている場合に備えて、引用符を追加しました。

私もこう変えました。ただ実行するコマンドを印刷します。スクリプトの出力を確認して、すべてのファイル/パス名が正しいことを確認してください。実行したいコマンドに問題がないと確信している場合は、そのコマンドを削除してくださいecho

関連情報