5

Suppose I am editing some files. I have (say) a terminal open and a gui file manager. I am currently in /my/very/long/and/winding/directory/path in the terminal. In my gui, I delete /my/very/long/and/winding/directory Back in the terminal, I try cd .. and I get an error, since the directory no longer exists. No big deal. I could type cd /my/very/long/and/winding to get back where I want to go. But if I'm too lazy to type that, is there a nice way to go back to the nearest directory that still exists?

edit: cd ../../ is one solution, in this particular case. But I'm wondering if there is a more general answer, where I don't know how many steps back I need to take.

1

3 Answers 3

6

To go back by one level of directory based on the directory path rather than the .. link:

cd $PWD:h

Or the portable method:

cd "${PWD%/*}"

(quotes optional in zsh; quotes optional in other shells if the directory name doesn't contain whitespace or \[*?)

Repeat the :h or /* as many times as desired to go further up in the directory hierarchy.

Alternatively, type cd $PWD then press Tab to expand $PWD to its value and manually edit the result. (Depending on your completion and line editor settings, you may need to add a / after $PWD before pressing Tab, to press the key that you've bound to expand-or-complete (default Tab) or expand-or-complete-prefix or expand-word (default Ctrl+X *).)

0
3

Assuming PWD is correct, one can back out in ZShell thusly.

% cd ~/tmp
% mkdir -p a/a/a/a/a/a/a/a/a/a/a
% cd !$
cd a/a/a/a/a/a/a/a/a/a/a
% rm -rf ~/tmp/a
% undir
% pwd
/Users/jmates/tmp
% 

The custom undir function does the walk-back-out-the-path-chain loop:

function undir {
  local dir
  dir=$PWD:h

  while [[ $dir != / ]]; do
    builtin cd -q $dir 2>/dev/null
    if [[ $? -eq 0 ]]; then
      dir=/
    else
      dir=$dir:h
    fi
  done
}

Note that you cannot rely on the pwd command, as that gives different results than the shell-maintained PWD variable:

% mkdir -p a/a/a/a/a/a/a/a/a/a
% cd !$
cd a/a/a/a/a/a/a/a/a/a
% rm -rf ~/tmp/a
% pwd
/Users/jmates/tmp/a/a/a/a/a/a/a/a/a/a
% cd ..
% pwd
.
% echo $PWD
/Users/jmates/tmp/a/a/a/a/a/a/a/a/a
% 

Shells that are not zsh will undoubtably require other solutions.

4
  • I hoped there might be a 'vanilla' bash solution, without using any custom functions. If not, I guess this is the next best thing!
    – SauceCode
    Commented Aug 25, 2015 at 23:54
  • @SauceCode - maybe like this for bash: p=$(dirname "$PWD"); while [[ ! -d "$p" ]]; do p=$(dirname "$p"); done; cd "$p" Commented Aug 25, 2015 at 23:59
  • @don_crissti Nice. With an alias that would be quite straightforward to use.
    – SauceCode
    Commented Aug 26, 2015 at 0:05
  • Note that in zsh you can do array[-1]=() to pop an element off the end on an array. See also $dir:h to get the dirname (head) of a path. Commented Aug 26, 2015 at 10:52
0

If you removed the directory you are in, cd .. will not work as the current directory exists without name and without connection to the rest of the world. So .. does no longer exist.

Every bourne shell alike should allow to write a function that creates a copy of $PWD and traverses the path as far as it still exists.

10
  • Posix shells and zsh fail as well. With regards to the bourne shell, you are mistaken. You may be right for a bourne shell before 1989. Modern shells including bourne track paths for symbolic links but this does not help here.
    – schily
    Commented Aug 26, 2015 at 12:49
  • You seem to missinterpret things. All modern shells just check where they are after chdir. All shells call chdir(".."). Ksh and zsh call chdir("$PWD/..") in addition but this of course fails as well.
    – schily
    Commented Aug 26, 2015 at 13:55
  • What I reported has been tested with bash, ksh and zsh. I tested the default behavior on Solaris. If you see different behavior, there must be constraint that causes the deviating behavior you observed.
    – schily
    Commented Aug 26, 2015 at 17:33
  • OK, that's part misunderstanding/talking about different things and Linux vs Solaris. After more checking, there's also some differences for bash between sh mode and non-sh mode. The behaviour of ksh88 and ksh93 also differs. Most of what you said and what I've said is true in some contexts and inaccurate in others. A long article would be needed here to summarize the different behaviours. See also Symbolic link recursion - what makes it “reset”? for some more info. I'll delete my comments for now. Commented Aug 26, 2015 at 19:37
  • OK, I checked ksh again and found that I was too quick and oversight somethiing; ksh does a stat on $PWD/. and this of course fails as well. So I cannot see a real different behavior. The funny notice for ksh is that if you recreate a directory of the same name of the removed directory, it "works" even though the state dis not change. My impression is that ksh does not follow the rules from the POSIX cd documentation. The way I understand the POSIX standard, even cd ../.. with two directories missing should result in a "successful" chdir to what the user expects.
    – schily
    Commented Aug 27, 2015 at 9:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .