我位于根目录中,里面有一些文件夹:
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 shortcut
shortcut
:如果文件与(使用 进行符号链接解析后-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 会忽略隐藏文件。添加D
glob 限定符或设置dotglob
选项以考虑它们。
答案3
尝试使用 prune 开关来排除目录,这应该可以回答您的问题:
find . -path ./your-folder -prune -o -maxdepth 1 -type d -print