使用 find 移动文件时保留目录结构

使用 find 移动文件时保留目录结构

我创建了以下脚本,将定义的旧文件从源目录移动到目标目录。它工作得很好。

#!/bin/bash

echo "Enter Your Source Directory"
read soure

echo "Enter Your Destination Directory"
read destination 

echo "Enter Days"
read days



 find "$soure" -type f -mtime "-$days" -exec mv {} "$destination" \;

  echo "Files which were $days Days old moved from $soure to $destination"

该脚本可以很好地移动文件,它还可以移动源子目录的文件,但不会在目标目录中创建子目录。我想在其中实现这个附加功能。

举例说明

/home/ketan     : source directory

/home/ketan/hex : source subdirectory

/home/maxi      : destination directory

当我运行此脚本时,它还会将十六进制的文件移动到 maxi 目录中,但我需要在 maxi 目录中创建相同的十六进制文件,并将其文件移动到相同的十六进制中。

答案1

我知道find已指定,但这听起来像是rsync.

例子

具有相同目录结构的镜像文件(源保持不变):

rsync -axuv --progress Source/ Target/

移动具有相同目录结构的文件(从源中删除并删除空目录):

rsync -axuv --prune-empty-dirs --remove-source-files --progress Source/ Target/

移动特定文件类型的文件(例子):

rsync -rv --include '*/' --include '*.js' --exclude '*' --prune-empty-dirs Source/ Target/

移动高级find搜索产生的文件:

cd "$source" &&
  rsync -av --remove-source-files --prune-empty-dirs --progress --files-from <(find . -type f -mtime -$days) . "$destination"

关于文件删除的说明

有一些选项rsync可以确保您的目标目录镜像您的源目录,然后删除目标中不再位于源中的文件(即--delete-before--delete-after--delete-during--delete-delay.

您还可以允许在文件从目标目录(即--remove-source-files.

这取决于用例,因此如何处理取决于您。

笔记:正如 Sridar Sarnobat 指出的那样,如果您将一个带有符号链接的目录 rsync 到您要 rsync 的目录,通过 --remove-source-files`,您最终可能会丢失数据。

答案2

mv /home/ketan/hex/foo /home/maxi您需要根据 生成的路径更改目标目录,而不是运行find。如果您首先更改到源目录并运行,这会更容易find .。现在您只需将目标目录添加到 . 生成的每个项目的前面即可find。您需要在find … -exec命令中运行 shell 来执行串联,并在必要时创建目标目录。

destination=$(cd -- "$destination" && pwd) # make it an absolute path
cd -- "$source" &&
find . -type f -mtime "-$days" -exec sh -c '
  mkdir -p "$0/${1%/*}"
  mv "$1" "$0/$1"
' "$destination" {} \;

请注意,为避免$destination包含特殊字符时出现引用问题,您不能仅在 shell 脚本中替换它。您可以将其导出到环境中,以便它到达内壳,或者您可以将其作为参数传递(这就是我所做的)。您可以通过对调用进行分组来节省一些执行时间sh

destination=$(cd -- "$destination" && pwd) # make it an absolute path
cd -- "$source" &&
find . -type f -mtime "-$days" -exec sh -c '
  for x do
    mkdir -p "$0/${x%/*}"
    mv "$x" "$0/$x"
  done
' "$destination" {} +

或者,在 zsh 中,您可以使用zmv功能,以及.m 全局限定符仅匹配正确日期范围内的常规文件。如果需要,您需要传递一个mv首先创建目标目录的备用函数。

autoload -U zmv
mkdir_mv () {
  mkdir -p -- $3:h
  mv -- $2 $3
}
zmv -Qw -p mkdir_mv $source/'**/*(.m-'$days')' '$destination/$1$2'

答案3

您可以使用 find(1) 的两个实例来完成此操作

总是有 cpio(1)

(cd "$soure" && find … | cpio -pdVmu "$destination")

检查 cpio 的参数。我给的那些

答案4

您可以通过将返回的文件的绝对路径附加find到目标路径来完成此操作:

find "$soure" -type f -mtime "-$days" -print0 | xargs -0 -I {} sh -c '
    file="{}"
    destination="'"$destination"'"
    mkdir -p "$destination/${file%/*}"
    mv "$file" "$destination/$file"'

相关内容