在linux上删除.git目录和.gitignore的所有内容

在linux上删除.git目录和.gitignore的所有内容,linux,bash,find,sh,ubuntu-14.04,Linux,Bash,Find,Sh,Ubuntu 14.04,嗨,我正在尝试使用linux命令行删除文件夹中的所有内容,除了.git目录和.gitignore文件 #!/bin/bash cd /git/ # remove old files find . ! -name '.gitignore' ! -path '.git' ! -path '.git/*' -exec rm -rf {} \; 它可以正常工作,它会删除所有东西,除了.gitignore文件。那么,我需要做些什么才能保留.git目录(包含所有的文件和文件夹!) 注意:将执行脚本的用户

嗨,我正在尝试使用linux命令行删除文件夹中的所有内容,除了
.git
目录和
.gitignore
文件

#!/bin/bash

cd /git/
# remove old files
find . ! -name '.gitignore' ! -path '.git' ! -path '.git/*' -exec rm -rf {} \;
它可以正常工作,它会删除所有东西,除了
.gitignore
文件。那么,我需要做些什么才能保留
.git
目录(包含所有的文件和文件夹!)

注意:将执行脚本的用户具有sudo权限

顺便说一句,当我用sudo sh cleanup.sh运行它时,控制台输出:

rm: cannot remove directory: ‘.’
find: `./.git': No such file or directory
find: `./foo': No such file or directory

我正在运行Ubuntu14.04

在这里使用
find
没有多大意义,因为您只想保留顶级
.git
目录和
.gitignore
文件(如果我理解正确的话)

请注意,
rm-rf
是一种递归删除,因此不需要遍历目录树来执行删除。由于
find
可能会选择执行
rm-rf./some_目录
,而它仍在扫描
some_目录
的内容,因此在
find
过程中执行递归删除可能会导致问题(例如find突然无法找到它认为知道的文件)

-path
谓词的参数用于匹配整个路径,从根参数开始(
,在本例中),因此
.git
将不匹配
/.git

总的来说,我建议(非常小心,首先使用echo进行测试):

rm
的第二个参数是一个扩展的glob,意思是“一个点后跟除以下以外的任何内容:nothing或一个点或
git
ignore
。排除
非常重要,尤其是在您拥有根权限的情况下。

您可以运行以下操作:

find -mindepth 1 -depth -print0 | grep -vEzZ '(\.git(/|$)|/\.gitignore$)' | xargs -0 rm -rvf
但首先模拟它会做什么:

find -mindepth 1 -depth -print0 | grep -vEzZ '(\.git(/|$)|/\.gitignore$)' | xargs -0 echo rm -rvf
说明:

-mindepth 1
:它将排除当前目录

-depth
:它将在文件夹之前列出文件


print0
:它将用一个空字符分隔每个记录,如果您的文件名包含空格,这很方便
-path
指的是
find
中的完整路径。git
不是完整路径,
/.git
是完整路径

因此,下面的方法可能会起作用

find . ! -name '.gitignore' ! -path './.git' ! -path './.git/*' -exec echo rm -rf {} \;
但是,它在相同的文件上仍然有两个递归点(
find
rm-r

find . -mindepth 1 -maxdepth 1 ! -name '.gitignore' ! -name '.git' -exec echo rm rf {} +
需要
-mindepth
,以避免将当前工作目录
作为文件处理


与之一样,删除
echo
以实际执行删除操作

您为什么要这样做?除此之外还有实际的目标吗?这似乎更适合unix.stackexchange.com,这不是一个编程问题。@wawawa看看我的答案,先模拟一下,让我知道它是如何进行的。谢谢
当前目录,对吗?那么我不需要排除
.git
而不是
git
.gitignore
而不是
gitignore
另一个选项是:
GLOBIGNORE='.git@(| ignore);
;这甚至不需要
shopt
ing
extglobignore
GLOBIGNORE='.?()“;shopt-s extglob;echo rm-rf!(.git | ignore)
@gniourf\u gniourf:都很好。但不管使用哪种技术,建议先用echo试试:)(像许多其他debian/ubuntu用户一样,我不必
shopt-s extglob
,因为可笑的过度复杂的制表符完成脚本可以帮我完成。但在vagrant上可能不是这样。)如果我运行
find-print0 | grep-vEzZ'(\.git |\.gitignore/)“
它输出
1:.7:./foo8:./foo/bar.txt9:./foo/bar 10:./foo/bar/baz.txt11:./bar.txt
。然后我看到两个问题:首先,当前目录
1:。
将被删除。其次,
-r
将删除
/foo/bar/
,而稍后它将再次尝试删除它。这可以通过删除
r选项,但我不知道如何排除当前目录。另一个问题是,为什么在.gitignore之后有一个
/
?它不应该在.git之后,因为那是一个目录吗?你没有管道到
xargs-0 echo rm-rvf
,它不会只删除打印rm-rvf,你就可以直接到当前目录了,so您可以使用
find-mindepth 1
,我将编辑answer@wawa我解决了您提到的两个问题。这不会删除像
test.git
这样的文件。顺便说一句,
.gitignore
文件被
grep
删除,因为它匹配
\、git
,而且它甚至不匹配您创建的
.gitignore//code>严格规定。
find . -mindepth 1 -maxdepth 1 ! -name '.gitignore' ! -name '.git' -exec echo rm rf {} +