【发布时间】:2010-08-11 12:57:13
【问题描述】:
在 shell 脚本中,我如何找到具有特定名称的文件,然后导航到该目录以对其进行进一步操作?
我将从这里将文件复制到另一个目录(但我已经可以这样做,只需将其添加到上下文中。)
【问题讨论】:
标签: linux shell filesystems
在 shell 脚本中,我如何找到具有特定名称的文件,然后导航到该目录以对其进行进一步操作?
我将从这里将文件复制到另一个目录(但我已经可以这样做,只需将其添加到上下文中。)
【问题讨论】:
标签: linux shell filesystems
你可以使用类似的东西:
pax[/home/pax]> cd "$(dirname "$(find / -type f -name ls | head -1)")"
pax[/usr/bin]> _
这将找到第一个 ls 常规文件,然后切换到该目录。
就每个位的作用而言:
/ 开始并向下搜索,列出所有名为ls (-name ls) 的常规文件(-type f)。您还可以向 find 添加其他内容,以进一步限制您获取的文件。head -1 的管道将过滤除第一个以外的所有内容。$() 是一种获取命令输出并将其放在另一个命令的命令行的方法。dirname 可以获取完整的文件规范并为您提供路径位。cd 只是更改到该目录。如果你按顺序执行每个位,你可以看到会发生什么:
pax[/home/pax]> find / -type f -name ls
/usr/bin/ls
pax[/home/pax]> find / -type f -name ls | head -1
/usr/bin/ls
pax[/home/pax]> dirname "$(find / -type f -name ls | head -1)"
/usr/bin
pax[/home/pax]> cd "$(dirname "$(find / -type f -name ls | head -1)")"
pax[/usr/bin]> _
【讨论】:
-type f 和 -name ls 之间留一个空格。
$() 周围应该有双引号(否则您的脚本将失败,路径包含空格和其他特殊字符):cd "$(dirname "$(find / -type f-name ls | head -1)")"
以下应该更安全:
cd -- "$(find / -name ls -type f -printf '%h' -quit)"
优点:
find 不会生成此类文件名,但它无害,并且可能需要类似的结构)-name 在-type 之前检查,因为后者有时需要stat
dirname,因为%h 说明符已经打印了目录名称-quit 在找到第一个文件后停止搜索,因此不需要 head 这将导致脚本在包含换行符的目录名称上失败【讨论】:
$ find . -name *.xsd 2) 添加 printf 和 -quit $ find . -name *.xsd -printf "%h" -quit 3) 用 backtics 包围并输入 cd (如果不需要,则省略):$ cd `find . -name *.xsd -printf "%h" -quit`
-printf '%h' 部分使得这个命令实际上什么都不返回,即使有文件......不太清楚为什么
path/to/folder: Is a directory。
没有人建议定位(对于大树来说更快)?
zsh:
cd $(locate zoo.txt|head -1)(:h)
cd ${$(locate zoo.txt)[1]:h}
cd ${$(locate -r "/zoo.txt$")[1]:h}
or could be slow
cd **/zoo.txt(:h)
重击:
cd $(dirname $(locate -l1 -r "/zoo.txt$"))
【讨论】:
基于this answer 的类似问题,其他有用的选择可能是使用 2 个命令,第一个是查找文件,第二个是导航到其目录:
find ./ -name "champions.txt"
cd "$(dirname "$(!!)")"
!! 是历史扩展,意思是“上一个命令”。
【讨论】:
扩展已经给出的答案,如果您想迭代地导航到find 找到的每个文件并在每个目录中执行操作:
for i in $(find /path/to/search/root -name filename -type f)
do (
cd $(dirname $(realpath $i));
your_commands;
)
done
【讨论】:
find 上的循环很脆弱:github.com/koalaman/shellcheck/wiki/SC2044
如果您只是查找文件然后将其移动到其他位置,只需使用 find 和 -exec
find /path -type f -iname "mytext.txt" -exec mv "{}" /destination +;
【讨论】:
-execdir 选项对我有用:find . -name foo.txt -execdir mv "{}" bar.txt ";" 在找到它的每个目录中将 foo.txt 重命名为 bar.txt。
function fReturnFilepathOfContainingDirectory {
#fReturnFilepathOfContainingDirectory_2012.0709.18:19
#$1=File
local vlFl
local vlGwkdvlFl
local vlItrtn
local vlPrdct
vlFl=$1
vlGwkdvlFl=`echo $vlFl | gawk -F/ '{ $NF="" ; print $0 }'`
for vlItrtn in `echo $vlGwkdvlFl` ;do
vlPrdct=`echo $vlPrdct'/'$vlItrtn`
done
echo $vlPrdct
}
【讨论】:
就这样,是不是很优雅?
cdf yourfile.py
当然你需要先设置它,但你只需要这样做一次:
将以下行添加到您的 .bashrc 或 .zshrc 中,无论您使用什么作为 shell 初始化脚本。
source ~/bin/cdf.sh
并将此代码添加到您需要从头开始创建的 ~/bin/cdf.sh 文件中。
#!/bin/bash
function cdf() {
THEFILE=$1
echo "cd into directory of ${THEFILE}"
# For Mac, replace find with mdfind to get it a lot faster. And it does not need args ". -name" part.
THEDIR=$(find . -name ${THEFILE} |head -1 |grep -Eo "/[ /._A-Za-z0-9\-]+/")
cd ${THEDIR}
}
【讨论】:
如果它是您PATH 中的程序,您可以这样做:
cd "$(dirname "$(which ls)")"
或在 Bash 中:
cd "$(dirname "$(type -P ls)")"
使用更少的外部可执行文件。
这不使用外部:
dest=$(type -P ls); cd "${dest%/*}"
【讨论】:
cd 在哪个 shell 中不需要引号? export d="foo bar"; mkdir "$d"之后:ksh -c 'cd $d'投诉cd: bad substitution; ash -c 'cd $d' 抱怨:can't cd to foo; bash -c 'cd $d' 抱怨:cd: foo: Not a directory.
cd 对通常的扩展规则没有特殊的豁免。而且您仍然缺少 dirname 参数周围的引号。
如果您的文件仅在一个位置,您可以尝试以下操作:
cd "$(find ~/ -name [filename] -exec dirname {} \;)" && ...
您可以使用 -exec 来调用 dirname 并使用 find 返回的路径(即 {} 占位符所在的位置)。这将改变目录。您还可以添加双与号 (&&) 以在 shell 更改目录后执行下一个命令。
例如:cd "$(find ~/ -name need_to_find_this.rb -exec dirname {} \;)" && ruby need_to_find_this.rb
它将查找该 ruby 文件,切换到目录,然后从该文件夹中运行它。此示例假定 文件名是唯一的,并且由于某种原因,ruby 脚本必须从其目录中运行。如果文件名不是唯一的,您将获得许多传递给 cd 的位置,它会返回一个错误然后它不会更改目录。
【讨论】:
试试这个。我创建了这个供我自己使用。
cd ~
touch mycd
sudo chmod +x mycd
nano mycd
cd $( ./mycd search_directory target_directory )"
if [ $1 == '--help' ]
then
echo -e "usage: cd \$( ./mycd \$1 \$2 )"
echo -e "usage: cd \$( ./mycd search_directory target_directory )"
else
find "$1"/ -name "$2" -type d -exec echo {} \; -quit
fi
【讨论】: