10

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

我的代码是:

#!/bin/bash 
cd /path/to/desired/directory
shopt -s extglob
rm !\(filename1\|filename2\|filename3\) -rf
cd -

我尝试了许多不同的方法来编写符号 '(' 和 '|',使用单引号或双引号或反斜杠,但没有任何效果。请注意,shopt -s extglobrm !(filename1|filename2) -rf脚本之外可以正常工作。

可能我犯了一个我看不到的标准和基本的 bash 脚本错误,但经验即将到来......

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

4

5 回答 5

9

我可以立即看到两个问题:

  • to的-rf参数rm必须文件名之前
  • extglob 说明符,!(不应使用反斜杠转义|)

试试这个:

rm -rf !(filename1|filename2|filename3)

如果它仍然不起作用,请删除该-f参数,您将收到有关问题所在的错误消息,而不是默默地压制它们。要打印出每个已删除文件的名称,您也可以添加该-v选项。

于 2013-11-05T05:33:31.497 回答
4

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

find . -not -regex "filename1|filename2|filename3" -print

检查输出并替换-print-delete是否仅打印您真正要删除的文件。

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

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

要摆脱所有空文件夹(并保留您要保留的文件):

find . -type d -empty -exec rmdir "{}" \;

(来源:如何在 Unix 中查找和删除空目录和文件

于 2013-11-05T08:06:06.040 回答
1

我不建议尝试编写规则来豁免特定文件。我更有可能做的是尝试在您要删除的文件的名称中找到文件掩码/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 中,您对文件名有一个长字符限制,以及用于在长名称周围导航的制表符完成。不要害怕自由地使用它们。

于 2013-11-05T10:37:14.313 回答
0

假设您有文件:

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 nodelete1

drwxr-xr-x 2 root root 4096 Feb 1 02:18 nodelete2

你可以这样做:

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

使用高级正则表达式语法排除文件。

解释:

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

grep -v --- v 标志指定不匹配的内容 + grep 如果您提供 -P 标志,则允许编写 perl 样式的正则表达式

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

于 2014-01-31T18:30:26.867 回答
0

试试下面:

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

祝你好运!

于 2013-11-05T07:52:36.933 回答