我需要只查找目录中的目录,但排除链接目录及其链接

我需要只查找目录中的目录,但排除链接目录及其链接

我位于根目录中,里面有一些文件夹:

0.1
0.2
0.3
0.4
0.5
0.6
shortcut -> 0.6

我需要列出没有快捷方式的上述目录以及 0.6 文件夹。我不会在此位置上方或任何这些文件夹内进行搜索。我这里可能也有一些文件,但我需要忽略它们。具有相同命名约定的新文件夹将不时添加到此目录中,因此此搜索将包含在 bash 脚本中,并且在添加新文件夹和运行脚本时将生成不同的结果。

我尝试过find -P . -maxdepth 1 -type d -ls但没有运气。

答案1

除了找到符号链接并跟踪它们之外,无法知道符号链接的目标名称是什么。

因此,我们可以这样做(假设bash版本 4.0 或更高版本):

#!/bin/bash

# Our blacklist and whitelist associative arrays (whitelist is a misnomer, I know)
# blacklist: keyed on confirmed targets of symbolic links
# whitelist: keyed on filenames that are not symbolic links
#            nor (yet) confirmed targets of symbolic links

declare -A blacklist whitelist

for name in *; do
    if [ -L "$name" ]; then

        # this is a symbolic link, get its target, add it to blacklist
        target=$(readlink "$name")
        blacklist[$target]=1

        # flag target of link in whitelist if it's there
        whitelist[$target]=0

    elif [ -z "${blacklist[$name]}" ]; then
        # This is not a symbolic link, and it's not in the blacklist,
        # add it to the whitelist.
        whitelist[$name]=1
    fi
done

# whitelist now has keys that are filenames that are not symbolic
# links. If a value is zero, it's on the blacklist as a target of a
# symbolic link.  Print the keys that are associated with non-zeros.
for name in "${!whitelist[@]}"; do
    if [ "${whitelist[$name]}" -ne 0 ]; then
        printf '%s\n' "$name"
    fi
done

该脚本应该以您的目录作为当前工作目录运行,并且不会对该目录中的名称做出任何假设。

答案2

如果您的意思是您想要所有类型的文件目录不是shortcut符号链接的目标,其中zsh

#! /bin/zsh -
printf '%s\n' *(/^e'{[[ $REPLY -ef shortcut ]]}')
  • (...):glob 限定符,根据名称之外的其他条件进一步过滤文件
  • /:仅此类型的文件目录
  • ^: 否定以下全局限定符
  • e'{shell code}':根据评估的结果(退出状态)选择文件shell code(其中正在考虑的文件位于$REPLY
  • [[ x -ef y ]]x:如果和y指向同一个文件(在符号链接解析之后),则返回 true 。通常,它通过比较两个文件的设备和索引节点号(通过stat()解析符号链接的系统调用获得)来实现这一点。

使用 GNU find(列表未排序,文件名前缀为./):

#! /bin/sh -
find -L . ! -name . -prune -xtype d ! -samefile shortcut
  • -L:对于符号链接,会考虑符号链接的目标。需要这样做才能完成与上面-samefile相同的操作。zsh-ef
  • ! -name . -prune:修剪除..相同, -mindepth 1 -maxdepth 1但更短且标准。
  • -xtype d:现在-L,我们需要在-xtype符号链接解析之前匹配原始文件的类型:
  • -samefile shortcutshortcut:如果文件与(使用 进行符号链接解析后-L)相同,则为 true

列出除目标目录之外的所有目录任何当前目录中的符号链接:

#! /bin/zsh -
zmodload zsh/stat
typeset -A ignore
for f (*(N@-/)) {
   zstat -H s -- $f &&
     ignore[$s[device]:$s[inode]]=1
}

printf '%s\n' *(/^e'{zstat -H s -- $REPLY && ((ignore[$s[device]:$s[inode]]))}')

请注意,zsh-bases 会忽略隐藏文件。添加Dglob 限定符或设置dotglob选项以考虑它们。

答案3

尝试使用 prune 开关来排除目录,这应该可以回答您的问题:

find . -path ./your-folder -prune -o -maxdepth 1 -type d -print

相关内容