Here’s an approach that’s a little less typing, but you need to be a bit careful with it.
It involves the !$
history reference (which jcbermu also used),
which means the last word of the most recent command.
(This is available in most shells: definitely bash
, csh
, and tcsh
.)
Append the :h
modifier to remove a trailing file name component,
leaving only the head, and your command is cd !$:h
.
In the following examples, the bold text is what you type:
~ $ vim /usr/share/drupal7/sites/all/modules/legacy/legacy.module
(edit the file)
~ $ cd !$:h
cd /usr/share/drupal7/sites/all/modules/legacy
/usr/share/drupal7/sites/all/modules/legacy $
It can handle spaces in the directory name, up to a point:
~ $ vim /usr/share/drupal7/sites/all/modules/old\ code/legacy.module
(edit the file)
~ $ cd !$:h
cd /usr/share/drupal7/sites/all/modules/old\ code
/usr/share/drupal7/sites/all/modules/old code $
or
~ $ vim /usr/share/drupal7/sites/all/modules/"old code"/legacy.module
(edit the file)
~ $ cd !$:h
cd /usr/share/drupal7/sites/all/modules/"old code"
/usr/share/drupal7/sites/all/modules/old code $
But, I think a good general statement is that it fails if the last /
in the filename is quoted:
~ $ vim "/usr/share/drupal7/sites/all/modules/old code/legacy.module"
(edit the file)
~ $ cd !$:h
cd "/usr/share/drupal7/sites/all/modules/old code
> Ctrl+C (Shell asks for continuation text
because it sees an unmatched quote character.)
It also fails if the file is in the current directory:
~ $ vim legacy.module
(edit the file)
~ $ cd !$:h
cd legacy.module
-bash: cd: legacy.module: No such file or directory
~ $ (:h has no effect because !$ doesn’t contain a /)
but that’s trivial.
If the file is in the current directory, you just wouldn’t do the cd
at all.
Another problem would be if you put the filename into a variable:
~ $ fn=/usr/share/drupal7/sites/all/modules/legacy/legacy.module
~ $ vim "$fn"
(edit the file)
~ $ cd !$:h
cd "$fn"
-bash: cd: /usr/share/drupal7/sites/all/modules/legacy/legacy.module: Not a directory
~ $ (:h has no effect because !$ (which is "$fn") doesn’t contain a /)
You can handle this as follows:
~ $ fn=/usr/share/drupal7/sites/all/modules/legacy/legacy.module
~ $ vim
(edit the file)
~ $ cd "${fn%/*}"
/usr/share/drupal7/sites/all/modules/legacy $
As the other answers suggested, use .
or "$PWD"
for the git add
command.
You could also just create a shell function with the same name. – slhck – 2015-03-06T10:22:40.833
@slhck Yes, you could - but it would reduce the usefullnes to the shell. Using a separate executable file makes the functionality available for every context – Eugen Rieck – 2015-03-06T10:45:24.047
I've got the "cdfile" as listed above, but it seems it changes the cwd just in the subshell - is that possible? – ptica – 2015-03-06T19:57:29.137
1Absolutely: it is not only possible, but inevitable and predictable that a
cd
in a shell script will affect only the rest of the script -- and if the script is only that one command, then "the rest of the script" is nothing. A script cannot affect the working directory of the parent shell that invokes the script. – Scott – 2015-03-08T07:59:52.033Depending on how you call the script - if you have no hashbang at the start you don't create a subshell. It definitly works here on CentOS 6.4 standard installation. – Eugen Rieck – 2015-03-10T18:38:26.250