如何在使用find命令时排除目录?


=Start=

缘由:

简单整理一下结论,方便后面有需要的时候参考。

正文:

参考解答:

question:
How do I exclude a specific directory when searching for *.js files using find?
在使用 find 搜索 *.js 文件时,我如何排除特定目录?

find . -name '*.js'

answer(s):

find -name "*.js" -not -path "./directory/*" #这个find命令还是遍历了你不想遍历的目录,因此如果希望速度快,就是用 -prune 选项

find . -path ./dir1 -prune -false -o -name "*.txt" #排除1个目录

find . -type d \( -path ./dir1 -o -path ./dir2 -o -path ./dir3 \) -prune -false -o -name "*.txt" #排除多个目录

find . -not \( -path ./dir1 -prune \) -name "*.txt" #符合预期,且如果你关心运行时间,并做任何远程密集的事情,你应该使用-prune。
find . -not \( -path ./dir1 -prune \) -not \( -path ./dir2 -prune \) -name "*.txt" #符合预期,且如果你关心运行时间,并做任何远程密集的事情,你应该使用-prune。


# 测试的文件目录结构
$ find . -type f -iname "*.txt"
./dir2/a.txt
./dir3/a.txt
./dir1/a.txt
./a.txt

# 这是 GetFree 的答案
$ find . -type f -iname "*.txt" -not -path "./dir1/*" #符合预期,起码结果里没有匹配的项目了(但是实际效果最慢,如果目录不大文件不多,也可以使用)
./dir2/a.txt
./dir3/a.txt
./a.txt

# 这是 f10bit 的答案
$ find . -type d \( -path ./dir1 -o -path ./dir2 -o -path ./dir3 \) -prune -o -name "*.txt" #不符合预期(但实际上是没问题的,它只是把不扫描的目录列出来了而已)
./dir2
./dir3
./dir1
./a.txt

# 【nice,推荐】这是在 f10bit 的答案下根据评论微调而成的
$ find . -type d \( -path ./dir1 -o -path ./dir2 -o -path ./dir3 \) -prune -false -o -name "*.txt" #符合预期,在【-prune】后面添加上【-false】即可
./a.txt

# 【nice,推荐】这是 Daniel C. Sobral 的答案,运行速度快,且可读性很高
$ find . -not \( -path ./dir1 -prune \) -name "*.txt" #符合预期,且如果你关心运行时间,并做任何远程密集的事情,你应该使用-prune。
./dir2/a.txt
./dir3/a.txt
./a.txt

# you can also exclude multiple paths
$ find . -not \( -path ./dir1 -prune \) -not \( -path ./dir2 -prune \) -name "*.txt" #符合预期,且如果你关心运行时间,并做任何远程密集的事情,你应该使用-prune。
./dir3/a.txt
./a.txt

# Reinstate Monica 答案里的测试脚本

#!/bin/bash

dir='.performance_test'

setup() {
  mkdir "$dir" || exit 1
  mkdir -p "$dir/prune_me/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/w/x/y/z" \
    "$dir/other"

  find "$dir/prune_me" -depth -type d -exec mkdir '{}'/{A..Z} \;
  find "$dir/prune_me" -type d -exec touch '{}'/{1..1000} \;
  touch "$dir/other/foo"
}

cleanup() {
  rm -rf "$dir"
}

stats() {
  for file in "$dir"/*; do
    if [[ -d "$file" ]]; then
      count=$(find "$file" | wc -l)
      printf "%-30s %-10s\n" "$file" "$count"
    fi
  done
}

name1() {
  find "$dir" -path "$dir/prune_me" -prune -o -exec bash -c 'echo "$0"'  {} \;
}

name2() {
  find "$dir" -not \( -path "$dir/prune_me" -prune \) -exec bash -c 'echo "$0"' {} \;
}

name3() {
  find "$dir" -not -path "$dir/prune_me*" -exec bash -c 'echo "$0"' {} \;
}

printf "Setting up test files...\n\n"
setup
echo "----------------------------------------------"
echo "# of files/dirs in level one directories"
stats | sort -k 2 -n -r
echo "----------------------------------------------"

printf "\nRunning performance test...\n\n"

echo \> find \""$dir"\" -path \""$dir/prune_me"\" -prune -o -exec bash -c \'echo \"\$0\"\'  {} \\\;
name1
s=$(date +%s%N)
name1_num=$(name1 | wc -l)
e=$(date +%s%N)
name1_perf=$((e-s))
printf "  [# of files] $name1_num [Runtime(ns)] $name1_perf\n\n"

echo \> find \""$dir"\" -not \\\( -path \""$dir/prune_me"\" -prune \\\) -exec bash -c \'echo \"\$0\"\' {} \\\;
name2
s=$(date +%s%N)
name2_num=$(name2 | wc -l)
e=$(date +%s%N)
name2_perf=$((e-s))
printf "  [# of files] $name2_num [Runtime(ns)] $name2_perf\n\n"

echo \> find \""$dir"\" -not -path \""$dir/prune_me*"\" -exec bash -c \'echo \"\$0\"\' {} \\\;
name3
s=$(date +%s%N)
name3_num=$(name3 | wc -l)
e=$(date +%s%N)
name3_perf=$((e-s))
printf "  [# of files] $name3_num [Runtime(ns)] $name3_perf\n\n"

echo "Cleaning up test files..."
cleanup
参考链接:

How do I exclude a directory when using find?
https://stackoverflow.com/questions/4210042/how-do-i-exclude-a-directory-when-using-find

Linux下用find命令一次查找多种类型的文件
https://ixyzero.com/blog/archives/2510.html

=END=

, , ,

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注