find + xargs - 将文件从一个子目录复制/移动到另一个子目录

find + xargs - 将文件从一个子目录复制/移动到另一个子目录

我的文件夹结构是这样的:

/volume1
  /photoTest
    /folderA
      /@eaDir
      /eaDir_tmp 
    /folderB
      /@eaDir
      /eaDir_tmp 
    /folder with space
      /@eaDir
      /eaDir_tmp 

我想做的是将文件从每个文件夹复制eaDir_tmp到各自的@eaDir文件夹中。

我能够通过以下方式让它进行:

for a in $(find /volume1/photoTest -type d -name eaDir_tmp); do rsync -vhar --chmod=a+rwx $a/ $a/../@eaDir; done;

直到我点击带有空格的文件夹。上面的脚本简直就是废话。

经过大量谷歌搜索后,我尝试了:

find /volume1/photoTest -type d -name eaDir_tmp -print0 | xargs -0 rsync -vhra --chmod=a+rwx {} {}/../@eaDir

该命令的试运行运行没有问题。但打印后实际运行就卡住了。

sending incremental file list
@eaDir/subdir1/

并卡在其上。

ps -elf | grep rsync显示一堆 rsync 进程的开启waitpoll_s状态。

有人知道发生了什么事吗?解决方案可能是什么?我想最终移动文件,但首先尝试复制,以便在出现问题时减少破坏性。

另外,我可以使用两个命令来让它工作,但有很多丑陋的地方:

# first, copy all files via:    
find /volume1/photo -type d -name eaDir_tmp -exec cp -a -t {}/../@eaDir {}/. \;

# second, change file permissions:    
find /volume1/photo -type d -name @eaDir -exec chmod 777 {} -R \;

但这很慢并且需要两倍的时间,更不用说与 rsync 可以做的相比非常有限。

一些背景信息:

  • 文件夹里面有什么eaDir?更多文件夹,然后是其中的一些文件。如果有帮助的话,整个事情是这样开始的:https://github.com/mbrrg/synology-thumbgen。作者建议删除现有@eaDir文件夹并简单地重命名eaDir_tmp.但我不能这样做,因为现有文件夹包含我想保留的文件。我可以解释,但我认为这会使问题进一步混乱。
  • 这是在我的 Synology NAS DSM 6.0+ 内,我认为它正在运行 BusyBox?但不确定。
  • 如果目标文件存在,那么如果源文件较新,我想覆盖它。否则不会。

答案1

find /volume1/photoTest -type d -name eaDir_tmp -prune \
    -exec sh -c 'rsync -a "$1"/ "${1%/*}/@eaDir"' sh {} ';' \
    -o -type d -name @eaDir -prune

这将查找名称eaDir_tmp位于 或之下的所有目录/volume1/photoTest。对于每个这样的目录,将执行以下命令:

rsync -a "$1"/ "${1%/*}/@eaDir"

其中$1是找到的目录的路径名。参数替换${1%/*}将删除路径名的最后一个组成部分,将 eg 变成/volume1/photoTest/folderA/eaDir_tmp/volume1/photoTest/folderA您也可以使用"$( dirname "$1" )")。

eaDir_tmp当我们找到任何找到的内容和目录时,我们会@eaDir从搜索列表中删除它们,并停止find输入它们。这是用 完成的-prune


find接受-execdir

find /volume1/photoTest -type d -name eaDir_tmp -prune \
    -execdir rsync -a eaDir_tmp/ @eaDir ';' \
    -o -type d -name @eaDir -prune

有关的:


使用zsh

for dirpath in /volume1/photoTest/*/eaDir_tmp(/DN); do
    rsync -a "$dirpath"/ "$dirpath:h/@eaDir"
done

使用bash

shopt -s dotglob nullglob
for dirpath in /volume1/photoTest/*/eaDir_tmp/; do
    rsync -a "$dirpath"/ "$(dirname "$dirpath")/@eaDir"
done

答案2

使用重击:

for a in volume1/photoTest/*
   do 
      pushd "$a"/eaDir_tmp
      cp -u * ../@eaDir          #... or rsync --chmod...
      popd 
   done

相关内容