脚本用于保留包含 .txt 文件的特定目录并从其他目录中删除不包含特定 .txt 文件的文件

脚本用于保留包含 .txt 文件的特定目录并从其他目录中删除不包含特定 .txt 文件的文件

我几乎完成了脚本,但它输出的是目录。我想要的是文件输出。你们中有人愿意帮我吗?:)

    #!bin/bash
( find /testftp/* -type d ;
  find /testftp/* -type f -iname DONOTDELETE.TXT -printf '%h'
) | sort | uniq -u

输出为:

/testftp/logs

输出是不存在 DONOTDELETE.TXT 的目录。非常接近。只需显示文件即可。

答案1

以下是我的看法:

#! /bin/bash

SPECIAL_FILE=DONOTDELETE
LOGFILE=clean.$(date +"%Y-%d-%m.%H%M%S").log   
FIND_BASE="$1"
if [ $# -ne 1 ]; then
        echo "Syntax $(basename $0) <FIND_BASE>"
        exit 1
fi
if [ "$FIND_BASE" = "." ]; then
        FIND_BASE=$(pwd)
else
        FIND_BASE=$(pwd)/$FIND_BASE
fi

for d in $(find $FIND_BASE -type d -print); do
        if [ "$d" != "$FIND_BASE" ]; then
                ls $d | grep $SPECIAL_FILE &> /dev/null
                if [ $? -ne 0 ]; then
                        echo "Deleting $d" | tee -a $LOGFILE
                        rm -rf $d 2>/dev/null
                else
                        echo "Ignoring $d, contains $SPECIAL_FILE" | tee -a $LOGFILE
                fi
        fi
done
exit 0

将其添加到脚本中,如果愿意,使用您自己的命名约定修改变量(对于特殊文件和日志名称),然后只需使用起始目录路径作为参数调用它即可。它将排除任何包含您想要的文件的目录,并删除所有其余目录。

答案2

我想我应该尝试一下这个。


#!/bin/bash
# file name and path can not have spaces for this to work.

ignorefile=DONOTDELETE.TXT
dir="`find /testftp/* -type d`";
exists=$(ls $dir | for each in $(find $dir -type f -iname $ignorefile -printf '%h\n'); do echo -en "grep -v $each |" ; done | sed '$s/.$//') 
direxists=$(ls $dir | eval $exists | grep -v $ignorefile | sed 's/:/\//g' | sort | uniq -u)

for pth in $direxists; 
do 
if [ -d $pth ]; then 
if [ "$(ls -A $pth)" ]; then 
echo rm -f ""$pth*""
fi
fi
done

复制:
更改了 dir="`find /testftp/* -type d`";
dir="`find ./testftp/* -type d`";

mkdir testftp && cd testftp
对于 1 2 3 4 5 6 7 8 9 中的 x;执行 mkdir $x;完成
对于 1 2 3 4 6 7 9 中的 y;触摸 $y/blah;完成
触摸 5/DONOTDELETE.TXT
触摸 5/some.log
触摸 8/DONOTDELETE.TXT
触摸 8/另一个.文件

光盘 ..
$ ./script.sh
rm -f ./testftp/1/blah
rm -f ./testftp/2/blah
rm -f ./testftp/3/blah
rm -f ./testftp/4/blah
rm -f ./testftp/6/blah
rm -f ./testftp/7/blah
rm -f ./testftp/9/blah

答案3

如果你有 bash 4+ (使用 检查bash --version),你可以用两行代码执行此操作:

shopt -s globstar
for f in ./**/; do [[ -f "$f"/DONOTDELETE.TXT ]] || rm -f "$f"/*; done

请注意,它shopt -s globstar需要占一行 - 不要仅仅用 将它添加到 for 循环前面;

./**/递归扩展到当前目录中的每个子目录及其子目录。如果您只想在树中向下移动一层,请使用代替./*/(并且不必费心设置 globstar);如果您想要更精细的控制,则必须使用代替find(特别是-maxdepth-mindepth选项)。如果您的任何目录以 : 开头,我会使用./**/代替,这样可以防止它们被视为**/-

[[ -f "$f"/DONOTDELETE.TXT ]]测试该文件是否存在并且是否是文件(如果您希望它即使 DONOTDELETE.TXT 可能不是文件也能正常工作,请使用-e而不是-f)。严格来说,您不需要在/那里,因为 $f 包含尾部斜杠,但我认为这样看起来更好,而且通常多余的正斜杠是无害的。||表示或 - 当(且仅当)该测试评估为错误的,那么它右边的代码将被执行,在本例中rm -f "$f"/*,它将删除除隐藏文件之外的所有文件。

如果您还想删除隐藏文件,可以使用以下命令:

for f in ./**/; do [[ -f "$f"/DONOTDELETE.TXT ]] || rm -f "$f"/* "$f"/.*; done

相关内容