4

What's the best way to go to a directory that contains a specific file? (Assuming we are starting at the root of where we wish to search). I'm using Cygwin.

SOLUTION: My final solution was to put this into my .bashrc file.

jump2_func() {
cd "$(find . -name $1 -printf %h -quit 2>/dev/null)"
}

alias jump2=jump2_func
5
  • You could write a script for this task.
    – John Goofy
    Aug 27, 2017 at 17:34
  • I figure it's probably a small script I put in my .bashrc file.
    – Dale
    Aug 28, 2017 at 7:08
  • 1
    @JohnGoofy But you cannot run that script regularly you have to source it. Aug 28, 2017 at 10:35
  • @HaukeLaging I know, while reading this question I started to write a little file manager and I got my first non-rc file that needs to be sourced.
    – John Goofy
    Aug 28, 2017 at 10:43
  • @Dale It is not recommended to blow up your ~/.bashrc with lots of scripts. You can use an alias or use/touch ~/.bash_aliases or ~/.bash_scripts.
    – John Goofy
    Aug 28, 2017 at 11:00

2 Answers 2

6

Two parts: Finding a file, and changing to the directory of a found file.

Finding a file

If you have the name of a file that you'd like to locate somewhere in the file hierarchy on your system, there are two ways that immediately springs to mind:

  1. Use find.
  2. Use locate.

To locate a file using find:

$ find / -type f -name "filename" -print

This will wander through the whole filesystem from the root (/) down and print out the full paths of all regular files called filename. Change / to whatever directory path you'd like to search from.

To find a file using locate:

$ locate -r -b '^filename$'

This will output all paths of all files (and directories, etc.) whose name is filename. This is usually much faster than using find. I'm using -r and a regular expression here to match complete filenames, otherwise you may get matches like file3 for a search of file. The -b option makes locate only match against the "base name" of the paths, i.e. the actual filename at the end of each path.

To be able to use locate on Cygwin, you would first have to initialize the "locate database". You do this by running

$ updatedb

The downside with locate is that it only knows about the locations of files present when updatedb was run. This is why most Unix system with locate usually runs updatedb (or the equivalent command) using cron (which I don't think is available in Cygwin) at regular intervals; once a day on some Linuxes, or once a week as is the default on OpenBSD.

Changing to the directory of a found file

Since neither of these methods are guaranteed to return only one file path, it's hard to come up with a sure-fire way of changing the working directory to the directory of the found file (if there are many, which one to choose?).

Assuming you'd like to pick the first result:

cd "$( dirname "$(somecommand | head -n 1)" )"

Here somecommand is either find or locate as above.

head -n 1 will pick out the first result out of the list, and dirname will extract only the path of the directory that contains the file. cd will then change the working directory to that directory.

Be aware that if you use locate, then the matches may also contain names of things that are not regular files (e.g. directories).

3
  • I agree that the updatedb would not work quite as well as I would like. Using ' find . -name SignatureDocumentService.java' as an example, the output that comes out is './files/SignatureDocumentService.java'. How can I cut off the last part so I can jump to the ./files directory? (Of course I'm looking for something I can use as a single command like 'jumpToFile SignatureDocumentService.java' )
    – Dale
    Aug 26, 2017 at 18:25
  • @Dale He answered that already: see the command that contains dirname. Aug 26, 2017 at 18:29
  • 1
    find ... -printf "%h" may also achieve the same effect for just retrieving the directory path string.
    – Pysis
    Aug 26, 2017 at 22:27
2
cd "$(find . -name filename -printf %h -quit 2>/dev/null)"

If no file with this name is found then cd changes into the home directory. If that is not wanted then you need something like this:

dir="$(find . -name filename -printf %h -quit 2>/dev/null)"
test -d "$dir" && cd "$dir"
1
  • Worked like a charm. This is exactly what I was looking for. Now I'll just put this in an alias so I can jump to the files I need to in the project I have
    – Dale
    Aug 28, 2017 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.