1

Is there a Unix command or shell script that takes a file argument and moves to the containing directory, ignoring the file part of the argument altogether?

3
  • 1
    moves - do you mean changes to as in cd? – Arkadiusz Drabczyk Aug 16 '20 at 18:46
  • Yes, that is what I meant. – Mike Harris Aug 16 '20 at 21:08
  • This must be done by the shell, not an external program, so which shell are you using? bash or something else? – Nathaniel M. Beaver Aug 17 '20 at 2:31
1

You could create a function, like this:

cd_to_file_location() {                          
    location=$(dirname -- "$1")
    cd -- "$location"
}

# test it out
$ mkdir /tmp/foodir
$ touch /tmp/foodir/a
$ cd_to_file_location /tmp/foodir/a 
$ pwd
/tmp/foodir
1
  • Double-quote your $1, otherwise it will fail on paths containing spaces – roaima Aug 16 '20 at 19:40
0

In zsh:

cdparent() cd -- $1:h

Will define a cdparent function that changes the current working directory to the directory part (head) of the first argument.

You can also do:

cd some/file(:h)

Where :h here is used in a glob qualifier again to retrieve the head of the given file.

The :h modifier comes from csh in the 70s where it could be applied to parameter expansion and history substitution. In zsh, it can be applied to those plus glob qualifiers. In bash, it can only be applied to history substitution. Some of those modifiers (including :h) are also available in vim, where you can do :cd %:h to chdir into the directory of the currently edited file for instance.

(the parent wording above can be a bit misleading in the case of cdparent .. for instance, which will do a cd . and not a cd ../.. as parent could suggest).

0

You can use a function that will check if a destination path is a directory and if it's not it will get the directory name from the path and cd to it. For example:

mycd()
{
    if [ ! $# -eq 1 ]
    then
        printf "Usage: mycd <PATH>\n" >&2
        return
    fi

    if [ ! -d "$1" ]
    then
        dest="$(dirname -- "$1")"
        set -- "$dest"
    fi

    cd -- "$1"
}

It's versatile enough to work with both directories and file paths and as it uses real cd you can always go back to the previous directory with cd -:

$ mkdir /tmp/test-dir/
$ touch /tmp/test-dir/FILE
$ mycd /tmp/test-dir/FILE
$ pwd
/tmp/test-dir
$ mycd /tmp/
$ pwd
/tmp
$ cd -
/tmp/test-dir
$ pwd
/tmp/test-dir
0

Are you looking for?

cd "${dirname "$1"}"

You can use pushd instead of cd as well depending on your needs.

2
  • $0 is the path to the shell (e.g. /bin/bash), not the first argument. – Nathaniel M. Beaver Aug 17 '20 at 1:36
  • Was sleepy yesterday, you're quite right. – Artem S. Tashkinov Aug 17 '20 at 12:13

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