Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash脚本以删除除特定文件和目录之外的所有文件和目录_Bash_Shell_Rm - Fatal编程技术网

Bash脚本以删除除特定文件和目录之外的所有文件和目录

Bash脚本以删除除特定文件和目录之外的所有文件和目录,bash,shell,rm,Bash,Shell,Rm,我正在尝试编写一个非常简单的bashshell脚本,它将cd放在一个特定的目录中,它将删除除一些选定的文件和目录之外的所有文件和目录,然后cd放回原始目录 我的代码是: #!/bin/bash cd /path/to/desired/directory shopt -s extglob rm !\(filename1\|filename2\|filename3\) -rf cd - 我尝试了许多不同的方法来编写符号“(”和“|”),使用单引号或双引号或反斜杠,但没有任何效果。请注意,shop

我正在尝试编写一个非常简单的bashshell脚本,它将cd放在一个特定的目录中,它将删除除一些选定的文件和目录之外的所有文件和目录,然后cd放回原始目录

我的代码是:

#!/bin/bash 
cd /path/to/desired/directory
shopt -s extglob
rm !\(filename1\|filename2\|filename3\) -rf
cd -
我尝试了许多不同的方法来编写符号“(”和“|”),使用单引号或双引号或反斜杠,但没有任何效果。请注意,
shopt-s extglob
rm!(filename1 | filename2)-rf
在脚本之外工作正常

也许我犯了一个我看不到的标准和基本的bash脚本错误,但经验将要到来

有什么建议吗!?
提前谢谢。

我可以马上看到两个问题:

  • rm
    -rf
    参数必须位于文件名之前
  • extglob说明符
    |
    不应使用反斜杠转义
请尝试以下方法:

rm -rf !(filename1|filename2|filename3)
如果它仍然不起作用,请删除
-f
参数,您将收到关于出错原因的错误消息,而不是静默抑制它们。要打印出删除的每个文件的名称,您还可以添加
-v
选项。

尝试以下操作:

for i in `ls | grep -v "file1\|file2\|file3"` ; do rm -rf $i; done

祝您好运!

如果您有最新版本的
查找
,请使用:

find . -not -regex "filename1|filename2|filename3" -print
检查输出并将
-print
替换为
-delete
,如果它只打印您确实要删除的文件

如果您的
find
版本不支持
-delete
,请使用
-type f-exec rm“{}”\;

请注意,这只会删除文件。这一点很重要:如果您说要保留文件
x
,但该文件位于文件夹
y
中,那么它将忽略
x
,直到稍后将其与整个文件夹
y
一起删除

要清除所有空文件夹(并保留要保留的文件),请执行以下操作:


(来源:)

我不建议尝试编写一个规则来豁免特定文件。我更可能做的是,尝试在要删除的文件名中找到一个文件掩码/glob,或其他一些锚,而您要保留的文件没有。在大多数情况下,您可能可以通过扩展名来完成。不可原谅当然,因为您没有提到任何文件的名称,所以我无法更具体地帮助您

类似于两个(或更多)查找循环:-

find *.mp3 d.mp3 -maxdepth 1 -type f | while read mp3s
do
mv $mp3s ~/d.stuff-to-keep
done    

find *.txt d.mp3 -maxdepth 1 -type f while read textfiles
do
rm -v $textfiles
done
如果没有,请查找文件的其他常见特征。如果没有,您可能需要重命名文件以给自己一个。我总是在文件名中添加许多锚(单独的名称字段、扩展名等),因为这样我就有很多不同的方法来处理这些文件。我通常的名称格式是:-

<extension>.+<author>+<year>+<work-name>+<volume-number>+<number-of-volumes>
+++++
加号是字段分隔符,破折号表示空格,但没有破折号作为第一个或最后一个字符。所有小写字母,不允许使用控制字符或其他非字母数字。因此,我可以使用awk、cut或任何我可能想使用的其他方法将其切分,并轻松重命名。将扩展名放在名称还意味着ls只需要一个标志(-l)就可以获得一个完全有序的文件系统

如果您知道如何使用基本POSIX工具将目录结构用作数据库,那么您有时就不需要安装任何更复杂的东西来完成您想要的任务


您在UNIX中对文件名有长字符限制,以及在长名称中导航的制表符完成。不要害怕自由地使用这两个选项。

假设您有文件:

drwxr-xr-x 2根根目录4096 Feb 1 02:17 a

drwxr-xr-x 2根根根4096 Feb 1 02:17 b

drwxr-xr-x 2根根目录4096 Feb 1 02:17 c

drwxr-xr-x 2根根部4096 Feb 1 02:17 d

drwxr-xr-x 2根根根4096 Feb 1 02:17 e

drwxr-xr-x 2根根部4096 Feb 1 02:17 f

drwxr-xr-x 2根根根4096 Feb 1 02:18节点1

drwxr-xr-x 2根根根4096 Feb 1 02:18节点2

你可以做:

ls|grep-v“nodel.\+”| xargs rm-rf

使用高级regexp语法排除文件

说明:

ls---列出当前目录(ls-d仅列出目录)

grep-v--v标志指定不匹配的内容,如果提供-p标志,grep允许编写perl风格的regexp


xargs--对每个项目应用操作“rm-rf”

您是否收到任何类型的错误?您确定
rm!(filename1 | filename2)-rf
在脚本之外工作正常吗?我希望改为
rm-rf!(filename1 | filename2)
(在操作数之前有选项)@ruakh我读了好几遍。我也经常在文件之后使用
rm
上的选项。也许这有点不一致,但对我来说总是有效的。@mario你不必用
cd-
切换回目录,因为在执行脚本时会使用子shell。@bashphil好的,'cd-'是一个细节,可能不是eded。谢谢你指出。@ruakh是的,我确信它是有效的。选项的位置-abc…不应该扮演任何角色。只是要谨慎一点,因为-rf会在未经请求的情况下删除文件,可能会有一些严重的数据丢失。我发现了错误。我把bash和sh混淆了(我仍然不理解他们的区别)。rm-rf!(filename1 | filename2 | filename3)以及rm!(filename1 | filename2 | filename3)-rf在脚本内外都能正常工作。为什么不应该用反斜杠标记说明符?我一直在用bash 4.3.11获得
bash:!:找不到事件。
。看起来我忘了添加shopt行。请注意,如果文件夹或文件名中有空格,这将以各种方式失败。它也不适用于subfo文件夹。@Aaron Digulla至于空格,试试这个:对于
ls | grep-v“new folder”中的i\ | file2\ | fi
<extension>.+<author>+<year>+<work-name>+<volume-number>+<number-of-volumes>