【问题标题】:Bash script to recursively copy files and folders when subdir is not present当 subdir 不存在时,用于递归复制文件和文件夹的 Bash 脚本
【发布时间】:2015-12-16 13:21:25
【问题描述】:

我在一个目录树下存档了很多项目,其中一些项目中有一个 .git 文件夹。

我想做的是递归地将这些文件和目录复制到一个新的目的地,保持当前的结构——除了那些包含 .git 文件夹的目录,在这种情况下脚本应该运行一个命令(比如说“ echo",我稍后会更改它)后跟文件夹名称,而不创建或复制它。

任何帮助将不胜感激。

编辑:我会尝试更好地解释我自己:我需要复制每个文件和目录,除了那些包含 .git 的文件和目录,应该跳过它们并将它们的路径传递给另一个命令。在此示例中,路径 a/b/c/d 及其子文件夹应完全跳过,并应使用 echo 显示 a/b/c/d(为简洁起见,稍后我将用不同的命令替换它):

a
a/b
a/b/c
a/b/c/d/.git
a/b/c/d/e
a/b/c/d/f/g
a/b/c/e
a/b/d
a/c
b
b/c
...

【问题讨论】:

  • 完成后是否可以选择复制所有内容并使用 find 删除 .git 文件夹?
  • 看看rsync 及其exclude 选项。
  • 当你有一个包含a/.git、a/b/some.txt`和a/c/.git的目录树时,你想跳过a/b文件夹吗?
  • @WalterA 是的,没关系,只要为每个包含 .git 的文件夹运行命令(echo)(基本上我需要稍后使用不同的 git 命令重新创建它们) .是的,只要里面有 .git,一切都可以跳过。
  • 我删除了以ls -d */ 开头的答案。 @gniourf_gniourf 评论正确:不要解析 ls 的输出,尤其是 ls -d */ 太可怕了!我用带空格的目录进行了测试,但是当目录包含换行符时它会变得很疯狂。

标签: bash directory copy


【解决方案1】:

IIUC,下面的find one-liner 将完成这项工作:

find . -type d -mindepth 1 -maxdepth 1 -exec sh -c "test -e '{}/.git' && echo not copy '{}' || cp -r -- '{}' /tmp/copy-here " \;

【讨论】:

  • {} 不应该这样使用!你允许任意代码执行。相反,请使用-exec sh -c 'test -e "$0/.git" && echo "not copy $0" || cp -r "$0" /tmp/copy-here' {} \;。此外,修饰符-mindepth 1 和-maxdepth 1 最好放在谓词前面;并且它们并非在 find 的所有版本中都可用。实际上,您可以用 shell 循环替换 find 语句:for f in */; do if [ -d "${f}.git" ]; then echo "not copy $f"; else cp -r -- "$f" /tmp/copy-here; fi; done。
  • 1.当{} 不安全时,你能举个例子吗? 2、为什么把mindepth和maxdepth放在开头比较好? 3. 是的,我知道POSIX 没有指定这些选项,但 OP 没有说明他使用的find 的版本和GNU find 很有可能 4. 是的,我知道可以通过循环来完成,我只是选择了find,因为我更喜欢它。
  • 哦,我忘了 - 在cp -r 后面加上一个双减号是个好主意,我修改了答案
  • 1.你去吧:如果你有一个名为'; ls # 的目录,那么命令ls 将被执行(你很高兴我只伪造了一个友好的文件名……用任何邪恶的命令替换ls 并哭泣)。
  • 2. -mindepth和-maxdepth,以及-depth修改find解析目录树的方式;它们不是像-type 或-exec 这样的谓词(即使它们被视为评估为真的主要)。这就是为什么我说他们应该先来。实际上,我的 find 版本会抱怨如果它们没有出现在其他谓词之前。
猜你喜欢
  • 2011-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
  • 2011-08-23
相关资源
最近更新 更多