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

KK *_*tel 29 bash find shell-script rename

我创建了以下脚本,将定义的旧文件从源目录移动到目标目录。它运行良好。

#!/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"
Run Code Online (Sandbox Code Playgroud)

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

举例

/home/ketan     : source directory

/home/ketan/hex : source subdirectory

/home/maxi      : destination directory
Run Code Online (Sandbox Code Playgroud)

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

rya*_*lon 27

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

我最常使用以下内容:

rsync -axuv --delete-after --progress Source/ Target/
Run Code Online (Sandbox Code Playgroud)

如果您只想移动特定文件类型的文件(example),这是一个很好的示例:

rsync -rv --include '*/' --include '*.js' --exclude '*' --prune-empty-dirs Source/ Target/
Run Code Online (Sandbox Code Playgroud)

  • 我发现 `--remove-source-files` 很有帮助,它有效地导致文件被移动而不是复制。这是 rsync 的一个很棒的用法。 (4认同)

Gil*_*il' 20

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" {} \;
Run Code Online (Sandbox Code Playgroud)

请注意,如果$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" {} +
Run Code Online (Sandbox Code Playgroud)

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

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