简体   繁体   中英

Bash: cd to directory provided by program output

I have a short shell program that returns a system path. What I want to do is CD to that path using a bash alias.

My ideal output is

~$ pwd
    /home/username
~$ mark home
~$ cd /
/$ pwd
    /
/$ place home
~$ pwd
    /home/username

I have the "mark" part working, but the "place" is not:

alias place="cd \"~/marker.sh go $@\";"

My idea is that I want to cd to the output of ~/marker.sh go $@

The problem is that bash is interpreting this as one command, and gives the errors:

-bash: cd: ~/marker.sh go : No such file or directory
-bash: home: command not found

which I assume means that the shell is parsing the entire alias as a string.

I've tried various forms of quoting for the shell script part of the alias $(), ``, etc, but they either try to run the script on bash start, or don't execute at all and just remain a string.

I'm programming this mostly to learn bash commands, but I can't figure out this one part!

I'm running OSX 10.9 in iTerm 1.0.0.20130624, if that's important.

Edit: I understand that cd-ing inside a script won't work , which is why I'm trying to just return the correct path using my program and use the built-in alias system to do the actual changing of directories.

You want a function, not an alias:

place () {
    cd $( ~/marker.sh go "$@" )
}

Aliases do not take arguments; they simply expand in-place, with the arguments occurring after whatever the alias expanded to.

(You should always prefer a function to an alias unless the function cannot be adapted to do what you want.)

Use functions, not aliases or external bash script!

in your .bashrc or any file sourced by it, or any file that you will manually source, put this fully usable script!

declare -A _mark_dir_hash

mark() {
   [[ -z $1 ]] && { listmarks; return 0; }
   if [[ -n ${_mark_dir_hash[$1]} ]] && [[ $1 != ${_mark_dir_hash[$1]} ]]; then
       echo "Mark $1 was already set to ${_mark_dir_hash[$1]}... replaced with new mark"
   fi
   _mark_dir_hash[$1]=$(pwd)
}

place() {
   [[ -z $1 ]] && { echo >&2 "You must give a mark name to go to!"; return 1; }
   [[ -z ${_mark_dir_hash[$1]} ]] && { echo >&2 "Mark $1 unknown!"; return 1; }
   cd "${_mark_dir_hash[$1]}"
}

listmarks() {
   [[ -z ${!_mark_dir_hash[@]} ]] && { echo "No marks!"; return 0; }
   for i in "${!_mark_dir_hash[@]}"; do
      printf '%s --> %s\n' "$i" "${!_mark_dir_hash[@]}"
   done
}

removemark() {
   [[ -z $1 ]] && { echo >&2 "You must give a mark name to remove!"; return 1; }
   unset _mark_dir_hash[$1]
}

clearmarks() {
   _mark_dir_hash=()
}

Ha, I just realized you're on mac, so you might be stuck with an antique version of bash which doesn't support associative arrays. Too bad for you. Yet, this might be useful to other people using modern shells!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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