How to safely compile locally different versions of linux commands?

@Molski Did you read my post above in the “And Finally” section?

I wasn’t making changes to my profile or shell startup files. The only changes I was making was renaming the parted binary using the mv command.

I found that after doing that I had to open a new shell tab in Konsole or else $parted -v was giving me the wrong information back.

Flex

That’s because you assigned a filename as a value to a variable and then changed the filename without also changing the value of the variable.

It’s a bug in the biological unit between the keyboard and the chair, not in the shell. :smirk:

1 Like

How should I do it then instead of:

sudo mv /usr/local/sbin/parted-patched /usr/local/sbin/parted

So I don’t have to reload the shell?

Flex

Reassign the variable. :man_shrugging:

@Aragorn Despite your best efforts at trying to help me I’m afraid in this case:

  1. I don’t know which is the filename (/usr/local/sbin/parted ?)
  2. Which is the variable (/usr/local/sbin/parted-patched ?)
  3. I don’t know how to “reassign the variable”.
  4. I don’t understand why I would need to anything more than just use the mv command and expect $parted -v to have an understanding of what has changed.

If you prefer I can start another thread elsewhere.

Flex

Yes.

You had me confused there because you were referring to an alias, but your pasted shell output suggests that you invoke it via the variable $parted.

At this point, I have no idea how you invoke it, but if it is indeed a variable, then you must assign the new value to it… :point_down:

name-of-variable="new-value"

If it is an alias, then you must redefine the alias… :point_down:

alias name-of-alias="the-command-you-wish-to-invoke"

There you go again. $parted is a variable, not an alias.

Ok, let me try to explain myself as clearly as I can.

Here are some commands I have just tried from a BASH shell in my Manjaro PC Konsole:

You see what is in my PATH and that /usr/local/sbin comes before /usr/bin and that I have two binaries called parted each in two different locations.

  • /usr/local/sbin/parted is version 3.66
  • /usr/bin/parted is version 3.6.
[flex@thinkpad ~]$ echo $PATH
/home/flex/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/usr/lib/rustup/bin:/var/lib/snapd/snap/bin
[flex@thinkpad ~]$ which parted -a
/usr/local/sbin/parted
/usr/bin/parted
[flex@thinkpad ~]$ /usr/local/sbin/parted -v
parted (GNU parted) 3.6.6-c5bd-dirty
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by <http://git.debian.org/?p=parted/parted.git;a=blob_plain;f=AUTHORS>.
[flex@thinkpad ~]$ /usr/bin/parted -v
parted (GNU parted) 3.6
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by <http://git.debian.org/?p=parted/parted.git;a=blob_plain;f=AUTHORS>.
[flex@thinkpad ~]$ parted -v
parted (GNU parted) 3.6.6-c5bd-dirty
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by <http://git.debian.org/?p=parted/parted.git;a=blob_plain;f=AUTHORS>.
[flex@thinkpad ~]$ 
[flex@thinkpad ~]$ sudo mv /usr/local/sbin/parted /usr/local/sbin/parted-patched
[flex@thinkpad ~]$ 
[flex@thinkpad ~]$ which parted -a
/usr/bin/parted
[flex@thinkpad ~]$ parted -v
bash: /usr/local/sbin/parted: No such file or directory
[flex@thinkpad ~]$

I use the mv command to rename the parted binary in /usr/local/sbin to parted-patched. So I now only have one binary in my system called parted and that is the v3.6 parted in /usr/bin as confirmed by the command which parted -a.

My question:
At the end when I do $ parted -v why does it not see parted v3.6 but instead it says:
“bash: /usr/local/sbin/parted: No such file or directory”?

If I open a new shell, a new tab in Konsole, then parted -v does see the correct v3.6

Flex

Because your $PATH is a variable, and that variable is only read when you open a login shell, although what you say leads me to suspect that — at least on your system — it is also being read when starting an interactive shell. Maybe you have your $PATH defined in ~/.bashrc — normally it would in be ~/.bash_profile only.

Either way, the location of some of the commands in the $PATH is hashed, meaning that their location is read into a cache in memory, so that the shell doesn’t need to effectively scan each of the directories of the $PATH. Presumably that is what’s happening here, i.e. you changed the name of the executable, but it doesn’t correspond anymore to what’s in the cache.

1 Like

Did you create an alias?

alias | grep parted

command parted -v

If you create an alias in a shell it’ll work in that shell, when you open a new shell it doesn’t exist, unless you put it in your config (~/.bashrc or similar) first. :man_shrugging:

2 Likes

@Aragorn
" Either way, the location of some of the commands in the $PATH is hashed, meaning that their location is read into a cache in memory…"

Thanks for confirming what I suspected myself, yesterday, five posts ago.

@dmt
No, I did not create an alias. And if I had, by your logic, then parted -v would not work correctly when I opened a new shell window. But as I have described above in about five different posts, after I rename a binary, opening a new shell window is the only way parted -v will work correctly for me.

It seems reloading the shell is required after a simple binary file rename which I consider an inconvenient limitation of how the shell is designed to work.

Thank you all,

Flex

It would work if the first terminal had an alias defined and the second didn’t. You hadn’t told us anything that would preclude that, and people had mentioned aliases earlier.

Inconvenient indeed, but you can . ~/.bashrc (. is the same as source) instead of opening a new terminal/shell.

I forgot to switch to bash when testing earlier, and zsh doesn’t exhibit this issue. I should probably pay more attention to the prompt.

I can’t remember running into this before, but it’s been ages since I used bash as my shell.

1 Like

@dmt This thread has gone on so long I guess it’s become impossible to keep everything in mind. In my post above from 29 June after summarising every ones helpful advice I tagged on an extra “Add Finally” section which I should really have put in a separate thread. In there I wasn’t concerned about using an alias I was just asking for clarification about why renaming my patched parted binary from “parted-patched” to “parted” and back again was giving incorrect results when I then ran the parted -v within the same shell. No one seemed to notice that question!

I tried your suggestion and of course you are right, using an alias in .bashrc would ensure parted -v always gives a sensible result even within the same shell but that’s not really a convenient solution to let me rename a binary that’s in my PATH using the mv command from the shell to whatever I want and for it to be properly recognised within the same shell after I rename it.

Useful to know . ~/.bashrc reloads the shell with instructions from there but I might anyway switch to zsh since as you say it doesn’t have this issue.

Thank you!

Flex

1 Like

It seems I was a bit hasty on that, I thought I’d checked properly, but apparently not for zsh, so I was only partly right. Also I have a custom .zshrc, and there may be an option specified which creates this behaviour.

zsh properly detects when a file is missing and checks anew, but it does cache it and uses the file should it exist. I think the bash equivalent is shopt -s checkhash. My usage wouldn’t normally bring this caching to light.

However we can clear the hashing/caching before the prompt is shown, which will force a path search.

bash
# Add this to ~/.bashrc
PROMPT_COMMAND='hash -r'

# I'm using this to test
# both copies are the same
$ cat /usr/local/testy
#!/usr/bin/bash
echo $0


$ which testy
/usr/local/bin/testy
$ testy
/usr/local/bin/testy

$ sudo mv /usr/local/bin/testy{,.bak}
$ which testy
/usr/bin/testy
$ testy
/usr/bin/testy

$ sudo mv /usr/local/bin/testy{.bak,}
$ which testy
/usr/local/bin/testy
$ testy
/usr/local/bin/testy
zsh
# Add this to ~/.zshrc
precmd() { hash -r; }

# Again I'm using this to test
# both copies are the same
$ cat /usr/local/testy
#!/usr/bin/bash
echo $0

% which testy
/usr/local/bin/testy
% testy
/usr/local/bin/testy

% sudo mv /usr/local/bin/testy{,.bak}
% which testy
/usr/bin/testy
% testy
/usr/bin/testy

% sudo mv /usr/local/bin/testy{.bak,}
% which testy
/usr/local/bin/testy
% testy 
/usr/local/bin/testy