Skip to content

Instantly share code, notes, and snippets.

@viking
Last active March 25, 2024 16:25
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save viking/5851049 to your computer and use it in GitHub Desktop.
Save viking/5851049 to your computer and use it in GitHub Desktop.
Bash script for i3 to run a terminal in the same working directory as the current focused application
#!/bin/bash
# i3 thread: https://faq.i3wm.org/question/150/how-to-launch-a-terminal-from-here/?answer=152#post-id-152
CMD=xterm
CWD=''
# Get window ID
ID=$(xdpyinfo | grep focus | cut -f4 -d " ")
# Get PID of process whose window this is
PID=$(xprop -id $ID | grep -m 1 PID | cut -d " " -f 3)
# Get last child process (shell, vim, etc)
if [ -n "$PID" ]; then
TREE=$(pstree -lpA $PID | tail -n 1)
PID=$(echo $TREE | awk -F'---' '{print $NF}' | sed -re 's/[^0-9]//g')
# If we find the working directory, run the command in that directory
if [ -e "/proc/$PID/cwd" ]; then
CWD=$(readlink /proc/$PID/cwd)
fi
fi
if [ -n "$CWD" ]; then
cd $CWD && $CMD
else
$CMD
fi
@jjvilm
Copy link

jjvilm commented Apr 19, 2016

love it!

Copy link

ghost commented Aug 28, 2017

On my system, by default the pstree command sorts children by name, and I end up with this, which fails:

x-terminal-emul(5525)-+-bash(5527)
                      `-x-terminal-emul(5526)

It can be fixed by adding the -n argument to pstree:

  TREE=$(pstree -lpAn $PID | tail -n 1)

@doak
Copy link

doak commented Nov 25, 2019

I updated the script to get CWD more reliable (for my use case).
For instance, it uses current working directory of foreground Vim instance, but if Vim is stopped (Bash's job control), it uses the current working directory of its parent shell.

The patch for tmux (of @TiddoLangerak) is not incorporated.

@suchAdemon
Copy link

suchAdemon commented Apr 29, 2020

you can also get the information from i3-msg (as long as you terminal is able to update name/title with the path)
#!/bin/bash
cd "$(i3-msg -t get_tree | jq -r '.nodes | .[].nodes | .[].nodes | .[].nodes | .[].nodes | .[] | select( .focused==true) | [.name]' 2>&1 | sed -e '2!d;s/^.*://g;s/"$//g' | sed -e "s|^~|${HOME}|g")" || cd ~
/path/to/your/terminal

@kabeersvohra
Copy link

I also updated the script with inspiration of @TiddoLangerak's version to get it more reliable for my use case (gnome terminal + tmux), it takes advantage of the #{pane_active} functionality within tmux list-panes which means it's not necessary to hunt for the specific tmux PID. It also uses head for the pstree command because my tmux sessions seemed to be at the top of the tree.

@nsbgn
Copy link

nsbgn commented Jan 11, 2022

Be aware that you can use the process' tgpid to find the foreground process of the terminal. This is more reliable and avoids having to look through the process' children. It's what I did in https://github.com/slakkenhuis/scripts/blob/master/xcwd.sh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment