-2

I'm runnning fish shell for a test for a few days. So i decided to use my already shell script programs. All of them are working fine, except for one: mkcd

Here is the code:

#!/usr/bin/env bash
dir=$1
mkdir -p "$dir" 
cd "$dir" || exit 1

The expected behaviour is to create a new directory and automatically execute a cd to that directory. But it's not working that way. The program create the directories but doesn't move to the new directory.

This program is located in $HOME/.local/bin with these other programs:

gc* guntrack* lvim* mkcd* nvims* path* tao*

All of those other shell script programs just work

You can find them here: My dotfiles

This is my fish config, located in $HOME/.config/fish/config.fish:

fnm env --use-on-cd | source
zoxide init fish | source

set -gx PATH ~/.local/forfish $PATH

#THATS THE LINE WHERE I SPECIFY THE PATH TO PROGRAM
set -gx PATH ~/.local/bin $PATH

alias vif 'fd --type f --hidden --exclude .git --exclude .vscode --exclude node_modules --print0 | fzf --layout=reverse --height=50% --read0 --print0 --exit-0 | xargs -r -0 nvim'
alias vi nvim
alias vid "nvim ."
abbr g git
alias rm trash-put

I'm using Oh my fish

My fish version: fish, version 3.6.1

My bash version: GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)

About my system:

NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
BUILD_ID=rolling
ANSI_COLOR="38;2;23;147;209"
HOME_URL="https://archlinux.org/"
DOCUMENTATION_URL="https://wiki.archlinux.org/"
SUPPORT_URL="https://bbs.archlinux.org/"
BUG_REPORT_URL="https://bugs.archlinux.org/"
PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/"
LOGO=archlinux-logo

Note, I found a solution using fish functions, but I really want to understand why the shell script is not working.

Following the function in fish that works:

function makedir -d "Create a directory and cd"
    mkdir -p $argv
    cd $argv
end

This function works fine if you put it inside the config.fish file

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Micael Viana
  • 107
  • 8
  • `cd` _never has_ changed a parent directory's process. Not in fish, or bash, or any other shell, or even any non-shell program (except ones that do dirty ugly hacks that evade the UNIX process model, like connecting to the parent process in a debugger and forcing it to run a syscall). You can only change _your own_ directory, or that of other programs you start; you can't change the directory of the program that started you. – Charles Duffy Aug 28 '23 at 23:33
  • While I closed this with a bash duplicate, the same thing is true in programs written in _literally every other language that exists_. You need to convince your existing process (that is, fish) to change its own directory; a child process fish started can't change fish's own directory. It's not that the `cd` isn't executed, but that it only changes the directory of the child process; since it does so just before the child exits, the change -- while it succeeds -- is effectively meaningless. – Charles Duffy Aug 28 '23 at 23:35
  • BTW, this is _also_ true of `mkcd` even when you start it from bash; you'd need to `source mkcd` for it to work, otherwise it's only changing the directory of a process the moment before that process exits, returning you to your preexisting copy of bash in the same directory it was in before. I suspect that if you run `type mkcd` in bash you'll see that it's set up as a function, or an alias that calls `source`, or otherwise in some manner that _isn't_ just running your script as a subprocess. – Charles Duffy Aug 28 '23 at 23:39
  • "cd never has changed a parent directory's process. Not in fish, or bash, or any other shell, or even any non-shell". I'm using this script every single day in zsh and works. So, is there architectural difference between zsh and fish that made the script works in zsh? – Micael Viana Aug 29 '23 at 15:40
  • It absolutely does not work in zsh _unless_ you're sourcing it, or defining its contents as a function, or so forth. In zsh, `which mkcd` will tell you how it's defined (note that `which` only works this way in zsh; in bash, sh, &c., `which` is an external command that doesn't know about functions or aliases and so can't be used to answer this question accurately). – Charles Duffy Aug 29 '23 at 16:34
  • See https://replit.com/@CharlesDuffy2/FantasticDecisiveStructs#testme.zsh for an online repl demonstrating that even in zsh, your mkcd does not change the current working directory of the copy of zsh that started it. Feel free to update/modify/fork it. – Charles Duffy Aug 29 '23 at 16:41
  • 1
    @CharlesDuffy. You were right. I discovered the problem: I'm currently running zsh with oh-my-zsh, and oh-my-zsh has a function called `mkcd` on the codebase. The function: mkcd () { mkdir -p $@ && cd ${@:$#} } I was not sourcing, I was typing **mkcd** $name_of_directory and it was working. But just because it was a function implemented with the same name as my script. My script was not been called. It was the function being called. – Micael Viana Aug 29 '23 at 19:33

0 Answers0