Linux Ksh下如何排除子目录检查目录中是否存在文件
解决Ksh中检查$PATH目录是否存在普通文件的问题
我明白你的需求:现在的逻辑会把仅含子目录的PATH目录判定为“存在”,但你希望只有当目录里有普通文件(非子目录、非链接等)时才返回“存在”。下面给你两种可靠的实现方式,适配Ksh环境:
方法一:用find高效检查(推荐)
find命令可以精准定位普通文件,并且支持找到第一个匹配项就停止,效率很高:
#!/usr/bin/ksh # 将$PATH分割为目录数组,处理空条目(比如PATH开头/结尾的冒号) IFS=: read -r -a path_directories <<< "$PATH" has_regular_file=false for dir in "${path_directories[@]}"; do # 跳过空目录占位符和不存在的目录 if [[ -z "$dir" || ! -d "$dir" ]]; then continue fi # 在当前目录下查找第一个普通文件,找到就立即退出 # -maxdepth 1 确保不递归子目录;-type f 只匹配普通文件 if find "$dir" -maxdepth 1 -type f -print -quit | grep -q .; then has_regular_file=true break # 找到一个就不用继续检查其他目录了 fi done # 输出结果 if $has_regular_file; then echo "存在" else echo "不存在" fi
关键细节:
-maxdepth 1:限制find只检查目录的直接内容,不会深入子目录-type f:严格匹配普通文件(排除目录、符号链接、设备文件等)-quit:找到第一个匹配文件就停止搜索,避免不必要的遍历- 处理了$PATH中的空条目(比如
PATH=/usr/bin::/home/user/bin里的空值)和不存在的目录
方法二:用Glob匹配(纯shell内置,无外部命令)
如果你不想依赖find,可以用Ksh的glob功能来匹配文件,同样能实现需求:
#!/usr/bin/ksh IFS=: read -r -a path_directories <<< "$PATH" has_regular_file=false for dir in "${path_directories[@]}"; do if [[ -z "$dir" || ! -d "$dir" ]]; then continue fi # 匹配目录下的所有文件(包括隐藏文件,排除.和..) set -- "$dir"/* "$dir"/.[!.]* "$dir"/..?* # 遍历匹配结果,检查是否有普通文件 for file in "$@"; do # 跳过未匹配到文件时的glob原字符串 if [[ -f "$file" ]]; then has_regular_file=true break 2 # 跳出两层循环,直接结束检查 fi done done if $has_regular_file; then echo "存在" else echo "不存在" fi
关键细节:
- 三个glob模式
"$dir"/*、"$dir"/.[!.]*、"$dir"/..?*覆盖了所有可见文件和隐藏文件(排除.和..) -f判断会识别指向普通文件的符号链接(如果不需要识别符号链接,可以换成-f && ! -h "$file")- 用
break 2直接终止所有循环,提升效率
自定义调整
如果你需要把符号链接指向的文件也算作“存在”,只需要把find中的-type f换成-test -f,或者保留glob方法中的-f判断即可——-f会自动跟随符号链接判断目标是否为普通文件。
内容的提问来源于stack exchange,提问作者JoelBonetR
相关产品推荐
相关产品推荐

