Bash
我只需要在目錄中查找目錄,但不包括連結目錄及其連結
我在根目錄中,裡面有一些文件夾:
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
但沒有運氣。
除了找到符號連結並跟踪它們之外,沒有辦法知道符號連結的目標名稱是什麼。
因此我們可以這樣做(假設
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
該腳本應該以您的目錄作為目前工作目錄執行,並且不假設該目錄中的名稱。
如果您的意思是您想要不是符號連結目標的目錄類型的所有文件,請使用:
shortcut``zsh
#! /bin/zsh - printf '%s\n' *(/^e'{[[ $REPLY -ef shortcut ]]}')
(...)
: glob 限定符,用於根據其他條件進一步過濾文件,而不僅僅是名稱/
: 只有目錄類型的文件^
: 否定以下 glob 限定符e'{shell code}'
:根據評估的結果(退出狀態)選擇文件shell code
(正在考慮的文件所在的位置$REPLY
)[[ x -ef y ]]``x
: 如果並且y
指向同一個文件(在符號連結解析之後),則返回 true 。通常,它通過比較兩個文件的設備和 inode 編號(通過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
選項以考慮它們。