shell 如何在目录路径中找到(使用bash)具有特定名称的顶级文件?

ohfgkhjo  于 12个月前  发布在  Shell
关注(0)|答案(2)|浏览(149)

我有一个bash脚本,它运行mysql脚本,并从一个文件中获取mysql数据库名称,而不是让我输入它作为一个选项(这样我就不会错误地输入错误的名字)。我通过将mysql数据库名放在一个名为mysql_db_name的文件中来设置它,该文件要么与我正在运行的脚本在同一个目录下,要么在该目录的目录路径中:它可能在父目录中,父目录的父目录等。当我输入以下内容时,此bash脚本将运行mysql脚本:

bash_script mysql_script_name

字符串
我想让我的bash脚本在mysql_script_name脚本的路径中找到名为mysql_db_name的顶级文件。
我目前的代码片段是这样的:

MFILE=`find / -exec bash -c '[[ $PWD != "$1"* ]]' bash {} \; -prune -name mysql_db_name -print`


这通常可以工作,但如果在父目录中有另一个目录,其文件名为mysql_db_name,其目录名是当前目录名的子集。例如,如果存在:

parent/directory1/mysql_db_name
parent/directory11/mysql_db_name
parent/directory11/mysql_script_name.sql


然后如果我尝试在directory11中运行mysql_script_name,bash_script会失败。如果上面的directory1被命名为directory2,它就不会失败。
这个问题类似于Find file by name up the directory tree, using bash,但我不能让这些解决方案工作。

14ifxucb

14ifxucb1#

如果您知道文件名和它所在的目录路径,那么无论如何都没有合理的理由在这里使用find

path='/'
for dir in path to deepest possible dir containing the file; do
    path=$path/$dir
    test -e "$path/mysql_db_name" && break
done
test -e "$path/mysql_db_name" || { echo "$0: mysql_db_name not found" >&2; exit 2;}
: proceed to use "$path/mysql_db_name"

字符串
这将继续查找具有该名称的文件的最高目录。应该不难看出如何从最深的目录开始;这里是一种方法。

path=/path/to/deepest/possible/dir/containing/the/file
while [ "$path" ]; do
    test -e "$path/mysql_db_name" && break
    path=${path%/*}
done
test -e "$path/mysql_db_name" || { echo "$0: mysql_db_name not found" >&2; exit 2;}
: proceed to use "$path/mysql_db_name"

nxowjjhe

nxowjjhe2#

假设目录树不是无限深的,我们可以递归调用的shell助手函数将是有用的,它在zsh & bash中应该是一样的:

find_files_in_dir_branch() {
  # if there is a regular file in this dir, print its full path
  [ -f "$1" ] && readlink -f "$PWD/$1"

  # if we have reached the root dir, finish with an error
  if [ "$PWD" = / ] ; then 
    false
  # otherwise, run same function in a subshell, in parent dir
  else 
    (cd .. ; find_files_in_dir_branch "$1")
  fi 
}

find_farthest_file_named() {
  local candidates="$(find_files_in_dir_branch $1)"
  # are there any canditates at all? then print the last/farthest one
  [ -n "$candidates" ] && tail -1 <<< "$candidates"
}

# invoke as find_farthest_file_named [something]

字符串
把它变成一个单行代码有点长--无论如何把它放在一个函数中是实用的,因为我们可以很容易地看到当没有找到任何东西时它们是否以代码1退出。
示例用法:

/# mkdir -p /h/a/y/stack ### test dir structure
/# touch /needle /h/a/needle /h/a/y/stack/needle ### 3 needles in haystack
/# cd /h/a/y/stack/
/h/a/y/stack# find_farthest_file_named needle ; echo $? ### find root one and succeed
/needle
0
/h/a/y/stack# rm /needle 
/h/a/y/stack# find_farthest_file_named needle ; echo $? ### find middle one and succeed
/h/a/needle
0
/h/a/y/stack# rm /h/a/needle
/h/a/y/stack# find_farthest_file_named needle ; echo $? ### find last one and succeed
/h/a/y/stack/needle
0
/h/a/y/stack# rm needle 
/h/a/y/stack# find_farthest_file_named needle ; echo $? ### find none and fail
/h/a/y/stack# echo $?
1

相关问题