我有一个存储文件路径的列表,即(impl/src/main/java/org/jboss/weld/util/collections/multimaps.java
)。在存储之前,路径已转换为小写。
现在,我需要在 bash 脚本中访问该文件。有没有一个简单的命令来“修复”外壳并找到文件?为简单起见,假设该文件不存在具有不同情况的多个版本。另请注意,路径中的目录可能需要修复其大小写。
我考虑过使用 find,但您不能拥有完整路径,因此从根目录find . -iname multimaps.java
可能会返回多个文件,其中只有一个文件位于正确的目录结构中。
我需要正确的路径以最终出现在 bash 脚本中的变量中。
答案1
GNUfind
有一个-iwholename
谓词可以解决我的问题:
find . -iwholename ./impl/src/main/java/org/jboss/weld/util/collections/multimaps.java
要将其放入变量中:
cased=`find . -iwholename "$filepath"`
答案2
和zsh
:
setopt extendedglob
files=((#i)${(f)^"$(<file.list)"}(N))
printf '%s\n' $files
(其中file.list
包含小写路径列表的文件,每行一个)。
(#i)
: 不区分大小写的 glob (需要extendedglob
)${(f)"$expansion"}
:在换行符上拆分扩展(换行符)${^array}
:对数组进行大括号扩展类型的扩展。(N)
: nullglob glob 限定符(删除不匹配的 glob)。
对于单个文件,它只是:
setopt extendedglob
file=impl/src/main/java/org/jboss/weld/util/collections/multimaps.java
matches=((#i)$file)
(这里省略了,(N)
所以如果没有匹配的话你会得到一个错误)
等价的ksh93
是:
matches=(~(iN)"$file") # N for nullglob, otherwise the glob expands to itself
# instead of giving an error when it doesn't match.
bash
有一个nocaseglob
不区分大小写的选项。然而
匹配=($文件)
行不通的。你需要启用对每个路径组件进行通配(通过使用任何通配符运算符),如
shopt -s nocaseglob nullglob
matches=([i]mpl/[s]rc/[m]ain/[j]ava/[o]rg/[j]boss/[w]eld/[u]til/[c]ollections/[m]ultimaps.java)
对于任何支持[...]
glob 运算符的 shell(因此本质上,除了fish
),您还可以将 glob 重写为[iI][mM][pP][lL]/[sS][rR]...
等等。
请注意,它与 a 不同find . -ipath "./$file"
,shell 不需要爬行整个目录树。它首先读取当前目录以查找目录(或目录的符号链接!另一个区别find
)称为impl
orImpl
或ImPl
等,然后仅读取这些目录的内容以查找一些src
//SRC
等srC
。
另一个区别是,如果路径组件恰好包含全局运算符(例如impl/***src***/whatever
),它仍然可以正常工作。
答案3
在bash中:
shopt -s nocasematch globstar
for f in **; do for search in "${files[*]}"; do [[ $f == $search ]] && echo Found "$search" at: "$f"; done; done
nocasematch shell 选项告诉[[ ... == ... ]]
命令在比较字符串时忽略大小写。 globstar shell 可以进行**
强力 bash 模拟find
;它的不同之处find
在于它将跳过点文件(除非shopt -s dotglob
设置)并遵循符号链接。
答案4
避免为每个文件一次又一次扫描树的方法是列出目录树一次,然后在哈希表中查找路径的小写翻译。例如:
NL='
'
find . -name "*$NL*" -prune -o -print | awk '
!list_processed {paths["./" $0]; next}
tolower($0) in paths' file.list list_processed=1 -
(其中file.list
包含小写文件列表,每行一个)。
我们将跳过名称中带有换行符的文件(而不是进入目录),因为如果该列表是换行符分隔的,则它们不可能存储在列表中file.list
(并且会破坏后处理)。
但请注意,如果文件名也包含无效字符,则跳过将不起作用。请参阅字节与字符部分位于为什么循环查找的输出是不好的做法?更多细节。