简体   繁体   English

找到文件然后 cd 到 Linux 中的那个目录

[英]Find file then cd to that directory in Linux

In a shell script how would I find a file by a particular name and then navigate to that directory to do further operations on it?在 shell 脚本中,我如何通过特定名称找到文件,然后导航到该目录以对其进行进一步操作?

From here I am going to copy the file across to another directory (but I can do that already just adding it in for context.)从这里我要将文件复制到另一个目录(但我已经可以做到这一点,只需将其添加到上下文中即可。)

You can use something like:您可以使用以下内容:

pax[/home/pax]> cd "$(dirname "$(find / -type f -name ls | head -1)")"
pax[/usr/bin]> _

This will locate the first ls regular file then change to that directory.这将找到第一个ls常规文件,然后切换到该目录。

In terms of what each bit does:就每一位的作用而言:

  • The find will start at / and search down, listing out all regular files ( -type f ) called ls ( -name ls ).查找将从/开始并向下搜索,列出所有名为ls ( -name ls ) 的常规文件 ( -type f )。 There are other things you can add to find to further restrict the files you get.还有其他的东西,你可以添加到find进一步限制你的文件。
  • The piping through head -1 will filter out all but the first.通过head -1的管道将过滤掉除第一个之外的所有内容。
  • $() is a way to take the output of a command and put it on the command line for another command. $()是一种获取命令输出并将其放在另一个命令的命令行上的方法。
  • dirname can take a full file specification and give you the path bit. dirname可以采用完整的文件规范并为您提供路径位。
  • cd just changes to that directory. cd只是更改到该目录。

If you execute each bit in sequence, you can see what happens:如果你按顺序执行每一位,你可以看到会发生什么:

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]> _

The following should be more safe:以下应该更安全:

cd -- "$(find / -name ls -type f -printf '%h' -quit)"

Advantages:好处:

  • The double dash prevents the interpretation of a directory name starting with a hyphen as an option ( find doesn't produce such file names, but it's not harmful and might be required for similar constructs)双破折号防止解释以连字符开头的目录名作为选项( find不会产生这样的文件名,但它无害并且可能需要类似的结构)
  • -name check before -type check because the latter sometimes requires a stat -name检查之前-type检查,因为后者有时需要stat
  • No dirname required because the %h specifier already prints the directory name没有dirname必需的,因为%h符已经打印目录名
  • -quit to stop the search after the first file found, thus no head required which would cause the script to fail on directory names containing newlines -quit在找到第一个文件后停止搜索,因此不需要head会导致脚本在包含换行符的目录名称上失败

no one suggesting locate (which is much quicker for huge trees) ?没有人建议定位(这对于大树来说要快得多)?

zsh: 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)

bash:重击:

cd $(dirname $(locate -l1 -r "/zoo.txt$"))

Based on this answer to a similar question, other useful choice could be having 2 commands, 1st to find the file and 2nd to navigate to its directory:基于这个答案对一个类似问题,其他有用的选择也可以是具有两个命令,第一个找到的文件和第2导航到其目录:

find ./ -name "champions.txt"
cd "$(dirname "$(!!)")"

Where !!哪里!! is history expansion meaning 'the previous command'.是历史扩展,意思是“上一个命令”。

Expanding on answers already given, if you'd like to navigate iteratively to every file that find locates and perform operations in each directory:扩展已经给出的答案,如果您想迭代导航到每个目录中find定位和执行操作的每个文件:

for i in $(find /path/to/search/root -name filename -type f)
do (
  cd $(dirname $(realpath $i));
  your_commands;
)
done
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

}

如果您只是找到文件然后将其移动到其他地方,只需使用 find 和 -exec

find /path -type f -iname "mytext.txt" -exec mv "{}" /destination +;

Simply this way, isn't this elegant?就这样,是不是很优雅?

cdf yourfile.py

Of course you need to set it up first, but you need to do this only once :当然你需要先设置它,但你只需要这样做一次

Add following line into your .bashrc or .zshrc, whatever you use as your shell initialization script.将以下行添加到您的 .bashrc 或 .zshrc 中,无论您使用什么作为 shell 初始化脚本。

source ~/bin/cdf.sh 

And add this code into ~/bin/cdf.sh file that you need to create from scratch.并将此代码添加到您需要从头开始创建的 ~/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}
}

If your file is only in one location you could try the following:如果您的文件仅在一个位置,您可以尝试以下操作:

cd "$(find ~/ -name [filename] -exec dirname {} \\;)" && ...

You can use -exec to invoke dirname with the path that find returns (which goes where the {} placeholder is).您可以使用-exec使用 find 返回的路径(它位于{}占位符所在的位置)调用dirname That will change directories.那将改变目录。 You can also add double ampersands ( && ) to execute the next command after the shell has changed directory.您还可以添加双与号 ( && ) 以在 shell 更改目录后执行下一个命令。

For example:例如:
cd "$(find ~/ -name need_to_find_this.rb -exec dirname {} \\;)" && ruby need_to_find_this.rb

It will look for that ruby file, change to the directory, then run it from within that folder.它将查找该 ruby​​ 文件,切换到目录,然后从该文件夹中运行它。 This example assumes the filename is unique and that for some reason the ruby script has to run from within its directory.此示例假定文件名是唯一的,并且出于某种原因,ruby 脚本必须从其目录中运行。 If the filename is not unique you'll get many locations passed to cd, it will return an error then it won't change directories .如果文件名不是唯一的,你会得到许多传递给 cd 的位置,它会返回一个错误,然后它不会改变目录

If it's a program in your PATH , you can do:如果它是PATH的程序,则可以执行以下操作:

cd "$(dirname "$(which ls)")"

or in Bash:或在 Bash 中:

cd "$(dirname "$(type -P ls)")"

which uses one less external executable.它使用较少的外部可执行文件。

This uses no externals:这不使用外部组件:

dest=$(type -P ls); cd "${dest%/*}"

try this.试试这个。 i created this for my own use.我创建了这个供我自己使用。

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

cd -- "$(sudo find / -type d -iname "dir name goes here" 2>/dev/null)"

keep all quotes (all this does is just send you to the directory you want, after that you can just put commands after that)保留所有引号(所有这一切只是将您发送到您想要的目录,之后您可以在之后输入命令)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM