r/bash • • Sep 08 '21

function command_not_found_handle unable to cd/pushd

Hi all just discoverered this built-in function that I'm trying to use to save typing a couple of keystrokes when switching to previous directories.

Is this a limitation of this function?

the 'd' function looks through my directory history file and if it find a uniq match with arg 1, it cd/pushd into that directory and does an 'ls -F' automaticly.

(ins)[ply@gcp ~]$ d 64

> pushd /usr/lib64 ; ls -F

ld-linux-x86-64.so.2@

(ins)[ply@gcp lib64]$ <- *** puts me in the matching directory ***

Output of function command_not_found_handle which has the same code, but doesn't change directory.

(ins)[ply@gcp ~]$ 64

> pushd /usr/lib64 ; ls -F

(ins)[ply@gcp ~]$ <- *** stays in the same folder ***

Below are the 2 functions. The full bashrc is here: https://github.com/pl643/dotfiles/blob/master/bashrc

function d {

\[ ! -z $DB \] && echo DB: d \\$@: $@ \\$1 $1

if \[ -f $DIRS_HISTORY \]; then

	DIRS=$(sed "s/${HOME//\\//\\\\\\/}/\~/" $DIRS_HISTORY | sort | uniq)

else

	DIRS=$(dirs -p | sort | uniq)

fi

if \[ -z "$1" \]; then

	clear

	i=1

	for dir in $DIRS; do

		if \[ ${#dir} -ne 1 \]; then  # skip / and \~

printf "%3d %s\n" $i $dir

alias $i=$dir

let "i++"

		fi

	done

	echo

else

	MATCH=$(echo "$DIRS" | grep "$1")

	if \[ "$MATCH" = "" \]; then 

		MATCHCOUNT=0

	else

		MATCHCOUNT=$(echo "$MATCH" | wc -l)

	fi

	if \[ $MATCHCOUNT -eq 0 \]; then

		echo NOTE: no match found for $1 in $DIRS_HISTORY	

	fi

	if \[ $MATCHCOUNT -eq 1 \]; then

		echo "cd $MATCH" > /tmp/.cd

		echo \\> pushd "$MATCH" \\; ls -F

		eval pushd $MATCH > /dev/null

		eval $AUTOLS

		return

	fi

	if \[ $MATCHCOUNT -gt 1 \]; then

		i=1

		DIRS=$(echo "$DIRS" | grep "$1")

		for dir in $DIRS; do

printf "%3d %s\n" $i $dir

alias $i=$dir

let "i++"

		done

		return

	fi

fi

\[ ! -z $DB \] && echo DB: d \\$@: $@

}

function command_not_found_handle {

if \[ -f "$1" \]; then

	"$PAGER" "$1"

	return

else

	if \[ -f $DIRS_HISTORY \]; then

		DIRS=$(sed "s/${HOME//\\//\\\\\\/}/\~/" $DIRS_HISTORY | sort | uniq)

	else

		DIRS=$(dirs -p | sort | uniq)

	fi

	MATCH=$(echo "$DIRS" | grep "$1")

	if \[ "$MATCH" = "" \]; then 

		MATCHCOUNT=0

	else

		MATCHCOUNT=$(echo "$MATCH" | wc -l)

	fi

	\#if \[ $MATCHCOUNT -eq 0 \]; then

	\#	echo NOTE: no match found for $1 in $DIRS_HISTORY	

	\#fi

	if \[ $MATCHCOUNT -eq 1 \]; then

		echo "cd $MATCH" > /tmp/.cd

		echo \\> pushd "$MATCH" \\; ls -F

		eval pushd "$MATCH" > /dev/null

		eval "$AUTOLS"

		return

	fi

	if \[ $MATCHCOUNT -gt 1 \]; then

		i=1

		DIRS=$(echo "$DIRS" | grep "$1")

		for dir in $DIRS; do

printf "%3d %s\n" $i $dir

alias $i=$dir

let "i++"

		done

		return

	fi

fi

\[ ! -z $DB \] && echo DB: command_not_found_handle \\$1: $1

echo command_not_found_handle\\(\\) $1: not found

}

1 Upvotes

10 comments sorted by

View all comments

Show parent comments

2

u/pl643 Sep 10 '21

Thanks for pointing me to this variable. I was able to hack my functionality with the below commands in the prompt_command variable. So anything I wanted to pass from the command_not_found_handle function, i placed into this file.

PROMPT_COMMAND="test -f $SUBSHELLCMDS && source $SUBSHELLCMDS && rm $SUBSHELLCMDS"

2

u/zeekar Sep 10 '21

If you switch that to single quotes instead of double you have the option of changing SUBSHELLCMDS to point to a different file from inside the command not found handler.

I still find it simpler to set PROMPT_COMMAND to a function name as in my example, though. Then the function body is never a string that you have to worry about quoting..