Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9203239
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 17, 20262026-06-17T23:25:46+00:00 2026-06-17T23:25:46+00:00

I have two iTerm windows running zsh: one I use to documents in vim;

  • 0

I have two iTerm windows running zsh: one I use to documents in vim; the other I use to execute shell commands. I would like to synchronize the current working directories of the two sessions. I thought I could do this by outputting to a file ~/.cwd the new directory every time I change directories

alias cd="cd; pwd > ~/.cwd"

and creating a shell script ~/.dirsync that monitors the contents of ~/.cwd every second and changes directory if the other shell has updated it.

#!/bin/sh
echo $(pwd) > ~/.cwd
alias cd="cd; echo $(pwd) > ~/.cwd"
while true
do
  if [[ $(pwd) != $(cat ~/.cwd) ]]
  then
    cd $(cat ~/.cwd)
  fi
  sleep 1
done

I would then append the following line of code to the end of my ~/.zshrc.

~/.dirsync &

However, it did not work. I then found out that shell scripts always execute in its own subshell. Does anyone know of a way to make this work?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-17T23:25:47+00:00Added an answer on June 17, 2026 at 11:25 pm

    Caveat emptor: I’m doing this on Ubuntu 10.04 with gnome-terminal, but it should work on any *NIX platform running zsh.

    I’ve also changed things slightly. Instead of mixing “pwd” and “cwd”, I’ve stuck with “pwd” everywhere.

    Recording the Present Working Directory

    If you want to run a function every time you cd, the preferred way is to use the chpwd function or the more extensible chpwd_functions array. I prefer chpwd_functions since you can dynamically append and remove functions from it.

    # Records $PWD to file 
    function +record_pwd {
        echo "$(pwd)" > ~/.pwd
    }
    
    # Removes the PWD record file
    function +clean_up_pwd_record {
        rm -f ~/.pwd
    }
    
    # Adds +record_pwd to the list of functions executed when "cd" is called
    # and records the present directory
    function start_recording_pwd {
        if [[ -z $chpwd_functions[(r)+record_pwd] ]]; then
            chpwd_functions=(${chpwd_functions[@]} "+record_pwd")
        fi
        +record_pwd
    }
    
    # Removes +record_pwd from the list of functions executed when "cd" is called
    # and cleans up the record file
    function stop_recording_pwd {
        if [[ -n $chpwd_functions[(r)+record_pwd] ]]; then
            chpwd_functions=("${(@)chpwd_functions:#+record_pwd}")
            +clean_up_pwd_record
        fi
    }
    

    Adding a + to the +record_pwd and +clean_up_pwd_record function names is a hack-ish way to hide it from normal use (similarly, the VCS_info hooks do this by prefixing everything with +vi).

    With the above, you would simply call start_recording_pwd to start recording the present working directory every time you change directories. Likewise, you can call stop_recording_pwd to disable that behavior. stop_recording_pwd also removes the ~/.pwd file (just to keep things clean).

    By doing things this way, synchronization be easily be made opt-in (since you may not want this for every single zsh session you run).

    First Attempt: Using the preexec Hook

    Similar to the suggestion of @Celada, the preexec hook gets run before executing a command. This seemed like an easy way to get the functionality you want:

    autoload -Uz  add-zsh-hook
    
    function my_preexec_hook {
        if [[-r ~/.pwd ]] && [[ $(pwd) != $(cat ~/.pwd) ]]; then
            cd "$(cat ~/.pwd)"
        fi
    }
    add-zsh-hook preexec my_preexec_hook
    

    This works… sort of. Since the preexec hook runs before each command, it will automatically change directories before running your next command. However, up until then, the prompt stays in the last working directory, so it tab completes for the last directory, etc. (By the way, a blank line doesn’t count as a command.) So, it sort of works, but it’s not intuitive.

    Second Attempt: Using signals and traps

    In order to get a terminal to automatically cd and re-print the prompt, things got a lot more complicated.

    After some searching, I found out that $$ (the shell’s process ID) does not change in subshells. Thus, a subshell (or background job) can easily send signals to its parent. Combine this with the fact that zsh allows you to trap signals, and you have a means of polling ~/.pwd periodically:

    # Used to make sure USR1 signals are not taken as synchronization signals
    # unless the terminal has been told to do so
    local _FOLLOWING_PWD
    
    # Traps all USR1 signals
    TRAPUSR1() {
        # If following the .pwd file and we need to change
        if (($+_FOLLOWING_PWD)) && [[ -r ~/.pwd ]] && [[ "$(pwd)" != "$(cat ~/.pwd)" ]]; then
            # Change directories and redisplay the prompt
            # (Still don't fully understand this magic combination of commands)
            [[ -o zle ]] && zle -R && cd "$(cat ~/.pwd)" && precmd && zle reset-prompt 2>/dev/null
        fi
    }
    
    # Sends the shell a USR1 signal every second
    function +check_recorded_pwd_loop {
        while true; do
            kill -s USR1 "$$" 2>/dev/null
            sleep 1
        done
    }
    
    # PID of the disowned +check_recorded_pwd_loop job
    local _POLLING_LOOP_PID
    
    function start_following_recorded_pwd {
        _FOLLOWING_PWD=1
        [[ -n "$_POLLING_LOOP_PID" ]] && return
    
        # Launch signalling loop as a disowned process
        +check_recorded_pwd_loop &!
        # Record the signalling loop's PID
        _POLLING_LOOP_PID="$!"
    }
    
    function stop_following_recorded_pwd {
        unset _FOLLOWING_PWD
        [[ -z "$_POLLING_LOOP_PID" ]] && return
    
        # Kill the background loop
        kill "$_POLLING_LOOP_PID" 2>/dev/null
        unset _POLLING_LOOP_PID
    }
    

    If you call start_following_recorded_pwd, this launches +check_recorded_pwd_loop as a disowned background process. This way, you won’t get an annoying “suspended jobs” warning when you go to close your shell. The PID of the loop is recorded (via $!) so it can be stopped later.

    The loop just sends the parent shell a USR1 signal every second. This signal gets trapped by TRAPUSR1(), which will cd and reprint the prompt if necessary. I don’t understand having to call both zle -R and zle reset-prompt, but that was the magic combination that worked for me.

    There is also the _FOLLOWING_PWD flag. Since every terminal will have the TRAPUSR1 function defined, this prevents them from handling that signal (and changing directories) unless you actually specified that behavior.

    As with recording the present working directory, you can call stop_following_posted_pwd to stop the whole auto-cd thing.

    Putting both halves together:

    function begin_synchronize {
        start_recording_pwd
        start_following_recorded_pwd
    }
    
    function end_synchronize {
        stop_recording_pwd
        stop_following_recorded_pwd
    }
    

    Finally, you will probably want to do this:

    trap 'end_synchronize' EXIT
    

    This will automatically clean up everything just before your terminal exits, thus preventing you from accidentally leaving orphaned signalling loops around.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Im using c# .net windows form application. I have two comboboxes A and B
Windows Forms application (c#). I have two ComboBoxes. If I select an item in
I have a DataGridView with two DataGridViewComboBoxColumns. I want to use the selected item
I Have two listboxes when I drag One item from the source listbox I
I have a WPF windows app project, it has a window with two ListBox
I have 15 BackgroundWorers that are running all the time, each one of them
I have two custom QML elements for audio, one for playing music (and extends
I have a solution, that has two projects, the main one and a small
I am trying to achieve some thing one these lines ,I have two listboxes
I have a base windows forms class which contains two buttons: Ok and Cancel.

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.