如何使用find复制和删除扩展保持相同的子目录结构

我试图将所有文件从一个目录复制到另一个目录,同时删除所有文件扩展名。

From directory 0001: 0001/a/1.jpg 0001/b/2.txt To directory 0002: 0002/a/1 0002/b/2 

我已经尝试了几个发现… | xargs c … p没有运气。

递归副本很容易与tar 。 在你的情况下:

 tar -C 0001 -cf - --transform 's/\(.\+\)\.[^.]\+$/\1/' . | tar -C 0002 -xf - 

如果你没有tar --transform这可以工作:

 TRG=/target/some/where SRC=/my/source/dir cd "$SRC" find . -type f -name \*.\* -printf "mkdir -p '$TRG/%h' && cp '%p' '$TRG/%p'\n" |\ sed 's:/\.::;s:/./:/:' |\ xargs -I% sh -c "%" 

\之后没有空格,需要简单的行结束,或者你可以加入到一行,如:

 find . -type f -name \*.\* -printf "mkdir -p '$TRG/%h' && cp '%p' '$TRG/%p'\n" | sed 's:/\.::;s:/./:/:' | xargs -I% sh -c "%" 

说明:

  • find将找到所有在您的SRC(源)目录中有扩展名的纯文件
  • find的printf将准备所需的shell命令:
    • 命令在TRG(目标目录)创建所需的目录树,
    • 命令进行复制
  • sed做一些美容路径清理,(比如纠正/some/path/./other/dir)
  • xargs将占据整条线
  • 并用shell执行准备好的命令

但是,这会好得多:

  • 只需在第一步中做一个精确的副本
  • 在第二步重命名文件

更简单,更干净,更快速(不需要检查/创建目标子目录)!

这里有一些find + bash +安装,可以做到这一点:

 for src in `find 0001 -type f` # for all files in 0001... do dst=${src/#0001/0002} # match and change beginning of string dst=${dst%.*} # strip extension install -D $src $dst # copy to dst, creating directories as necessary done 

这将默认将所有复制文件的权限模式更改为rwxr-xr-x ,并使用install的--mode选项进行更改。

我想出了这个丑小鸭:

 find 0001 -type d | sed 's/^0001/0002/g' | xargs mkdir find 0001 -type f | sed 's/^0001//g' | awk -F '.' '{printf "cp -p 0001%s 0002%s\n", $0, $1}' | sh 

第一行创建目录树,第二行复制文件。 与此有关的问题是:

  1. 只有处理目录和常规文件(没有符号链接等)
  2. 如果文件名中有任何句号(除扩展名外)或特殊字符(空格等),则第二个命令将不起作用。