如何复制和重命名Linux“查找”功能中找到的文件?

如何复制和重命名Linux“查找”功能中找到的文件?

我有一个名为 的文件夹/home/user/temps,其中有 487 个文件夹。在每个文件夹中我都有一个名为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是一个坏主意——简单地使用 shell 扩展更可靠。另外,这是假设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

这一解决方案“扁平化”子目录和子子目录中的文件,使它们全部位于一个大目录中。新文件名反映原始路径。例如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

该命令也可以一行完成

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'

如果您不确定,请添加echotocp来查看将要执行的内容。

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

解释

这可以使用参数扩展: ${f//\//_}。它获取变量的内容f(其中包含带路径的文件名)并将每次出现的 替换/_

请注意,这是一个愚蠢的文本搜索和替换。如果两个不同的文件最终具有相同的名称,则其中一个文件将被覆盖。

例如两个文件temps/dir/thumb.pngtemps/dir_thumb.png.这两个文件都将被重命名为temps_dir_thumb.png.这样就会丢失一个文件。哪个文件将丢失取决于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" "$(basename "$(dirname "temps/thumb.png")")_$(basename "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 二/thumb.png" "$(basename "$(dirname "temps/dir 二/thumb.png")")_$(basename "temps/dir 二/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.

相关内容