在Unix中有条件的删除文件

3
我需要删除当前目录中除一个文件(例如abc.txt)外的所有文件。是否有任何命令可以删除目录中除abc.txt之外的其他文件?

1
请在https://dev59.com/z1LTa4cB1Zd3GeqPaW6C中查看答案。这不是一个命令,而是使用单独工具以Unix风格执行不同任务的常规方式。 - Edu
4个回答

5
如果您需要一个简洁的命令,那么使用bash中的扩展globbing,您应该能够使用以下命令: (了解更多)
rm !(abc.txt)

这种方法有一些需要注意的事项。
  1. This will run rm on all entries in the directory (apart from "abc.txt") and this includes subdirectories. You will therefore end up with the "cannot remove directory" error if subdirs exist. If this is the case, use find instead:

    find . -maxdepth 1 -type f \! -name "abc.txt" -exec rm {} \;
    # omit -maxdepth 1 if you also want to delete files within subdirectories.
    
  2. If !(abc.txt) returns a very long list of files, you will potentially get the infamous "argument list too long" error. Again, find would be the solution to this issue.

  3. rm !(abc.txt) will fail if the directory is empty or if abc.txt is the only file. Example:

    [me@home]$ ls
    abc.txt
    [me@home]$ rm !(abc.txt)
    rm: cannot remove `!(abc.txt)': No such file or directory
    

    You can workaround this using nullglob, but it can often be cleaner to simply use find. To illustrate, a possible workaround would be:

    shopt -s nullglob
    F=(!(abc.txt)); if [ ${#F[*]} -gt 0 ]; then rm !(abc.txt); fi  # not pretty
    

谢谢您有兴趣提供一个简单的命令。使用它有副作用吗?我看到其他人推荐使用if和循环的shell脚本。请给建议。 - Arun
有时我会发现Putty会抛出“!event not found”错误。你能给予建议吗? - Arun
是什么命令导致了这个问题?听起来你不小心调用了history命令。请确保使用括号,例如使用rm !(event)而不是rm !event - Shawn Chin
很抱歉,我无法重现该错误,因此很难确定问题出在哪里。一个快速的解决方法是通过运行 set +H 来暂时禁用历史命令。 - Shawn Chin
哦,我真的不会执行 rm -rf ...,除非我确切知道它将匹配哪些文件。一旦失误,你可能会删除更多的文件。 - Shawn Chin
显示剩余2条评论

3

1)

mv abc.txt ~/saveplace
rm *
mv ~/saveplace/abc.txt .

2)

find . ! -name abc.txt -exec rm {} "+"

如果我必须做这样的事情 - 我会选择1)。 - Tsvetomir Dimitrov
@tsurko:是的,我也同意使用1),但我想要尽量简化我的发布说明,减少步骤数量。 - Arun

2

尝试

find /your/dir/here -type f ! -name abc.txt -exec rm {} \;

1

如果文件名中没有空格,您可以使用for循环遍历ls的结果:

for FILE in `ls -1`
do
   if [[ "$FILE" != "abc.txt" ]]; then
      rm $FILE 
   fi 
done

你可以将它写成脚本,或者直接在bash提示符下编写:先写第一行,然后按下enter键,接着你可以写其他行,bash会等待你写完done再执行。否则,你可以将其写成单行:

for FILE in `ls -1`; do if [[ "$FILE" != "abct.txt" ]]; then rm $FILE; fi; done

如果文件名中有空格,这将会出错。 - Shawn Chin
@ShawnChin,你说得对。已在答案中指明。 - Zagorax

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接