I am using the terminal (iTerm2, Terminal) to work inside of a git repository. The working directory contained no other files or folders. I created a folder "Foo" using git clone <url>, then deleted it using git rm -f Foo, leaving the working directory empty. I created a new folder using svn export url. Renaming that folder to "Foo" works with no errors, then a couple of seconds later, the folder is renamed to "Foo 2".
The verbose option mv -v Foo\ 2 Foo just prints Foo\ 2 -> Foo. I've tried restarting both terminals. I'm using MacOS Monterey 12.6.1.
mv Foo\ 2 Foo works successfully.
ls prints Foo if less than a few seconds have passed since 1, else Foo 2
ls Foo prints the many contents of Foo if less than a few seconds have passed since 1, else ls: Foo: No such file or directory
Related
I wanted to change current directory into shell script into directory, containing specific regular file. I found that following trick works in mksh and busybox sh:
path=/path/to/regular/file
cd $path/..
but not in GNU Bash:
bash: cd: /path/to/regular/file/..: Not a directory
Is this trick not posix-compatible, or Bash is too pedantic?
Latest edition of the standard doesn't allow that. POSIX.1-2017 cd spec. says that if the pathname component preceding dot-dot is not a directory, cd shall consider that an error.
From cd § DESCRIPTION - step 8.b:
b. For each dot-dot component, if there is a preceding component and
it is neither root nor dot-dot, then:
i. If the preceding component does not refer (in the context of
pathname resolution with symbolic links followed) to a
directory, then the cd utility shall display an appropriate
error message and no further steps shall be taken.
When cd is invoked with -P option, this step is omitted; but then chdir() fails if one of the pathname components names an existing file that is neither a directory nor a symbolic link to a directory.
Besides, permitting that trick also allows inconsistent behavior in cd. For example, when run in a directory containing a regular file named bar, and a directory named foo containing another directory named bar, the following two commands do different things in a shell where cd ignores non-directory components preceding a dot-dot, despite that CDPATH contains the empty string (i.e. the current working directory) in both cases.
CDPATH= cd bar/..
CDPATH=:foo cd bar/..
Below transcripts visualize the difference between non-conforming and conforming implementations clearly.
$ tree -F
.
├── bar
└── foo/
└── bar/
2 directories, 1 file
$ ash
$ CDPATH= cd bar/..
$ pwd
/home/oguz
$ CDPATH=:foo cd bar/..
/home/oguz/foo
$ bash
$ CDPATH= cd bar/..
bash: cd: bar/..: Not a directory
$ CDPATH=:foo cd bar/..
/home/oguz/foo
bosh, gwsh, ksh93u+m, and yash are other actively maintained shells that implement the same behavior as bash.
This command prints the directory name just fine:
echo ${PWD##*/}
This alias in .bashrc does not:
alias echodir="echo ${PWD##*/}"
They both work fine in the home directory, but after changing directories only typing it in manually works. The alias still prints the home folder. I understand this is because git bash works with nested shells or something - the base shell doesn't change directories at all, but the surface one does.
Is there a way to create an alias that works as expected?
I'm just posting the answer twalberg put in the comments(he gets the credit):
As a one-off command:
echo "-----Updating "${PWD##*/}"-----"
As an alias:
alias updating='echo "-----Updating "${PWD##*/}"-----"'
I've been creating commands that jet me to my folder I want to work within, and it's great, but...
Could there be a way to add the command automatically whenever I create a new folder?
E.g., I make a folder on my comp, and this gets added to my bash profile:
alias foldername='cd /Applications/MAMP/htdocs/foldername/wp-content/themes/foldername'
I'm on a mac; el capitan.
You can create a function in your .bashrc:
# Changes directory to project in htdocs
function project () {
cd "/Applications/MAMP/htdocs/$1"
}
Once you've sourced the bashrc or started a new shell you can navigate through to sub folders of htdocs using
project FOLDER_NAME
If you are willing to install a newer version of bash (via Homebrew, for instance), you can set the autocd option.
$ shopt -s autocd
$ pwd
/Users/me
$ mkdir foo
$ foo
cd foo
$ pwd
/Users/me/foo
The version of zsh that ships with Mac OS X has an identically named option, if you are willing to change shells.
% setopt autocd
% pwd
/Users/me
% mkdir foo
% foo
% pwd
/Users/me/foo
You could also use CDPATH environment variable for this sort of thing (assuming your target directories live under a common directory (or three).
From the POSIX specification for cd:
CDPATH
A <colon>-separated list of pathnames that refer to directories. The cd utility shall use this list in its attempt to change the directory, as described in the DESCRIPTION. An empty string in place of a directory pathname represents the current directory. If CDPATH is not set, it shall be treated as if it were an empty string.
So if you set CDPATH=.:/Applications/MAMP/htdocs/foldername/wp-content/themes you could then just use cd foldername from anywhere to go to /Applications/MAMP/htdocs/foldername/wp-content/themes/foldername... assuming of course that there wasn't a directory foldername in your current directory (if you wanted it to work for that too you would need to invert the order of the items in CDPATH).
Another approach referenced in the comment is the create a simple function that creates and changes to a directory. Aliased to mdcd it does just that creates and on successful creation changes to the directory. I use it in my ~/.bashrc:
mkdircd ()
{
[ -z "$1" ] && {
printf "usage: mdcd <dir>\n";
return 1
}
mkdir -p "$1" && cd "$1" || {
printf "error: unable to create directory '%s'\n" "$1";
return 1
}
return 0
}
...
alias mdcd='mkdircd'
You can give it a try and see if it fits your needs.
Under Mac OSX (Mountain Lion), I have a shell script "a":
#!/bin/bash
open -a Terminal b
which run another shell script "b" using Terminal:
echo `pwd`
Something interesting is that, no matter where my running scripts are located, the pwd command in "b" always returns the home directory.
Questions:
Why does this happen?
How to set the running environment to be the working instead home directory (ie, return the working directory when arriving at pwd)
This will probably work in b:
echo $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
I am a ubuntu Linux user but I'm pretty sure the cli is very similar for both. Anyways, I believe the default directory when you open a new terminal window is your home directory. Unless you change it within your settings. This is the likely reason for the pwd command in "b" printing your home directory.
I was wondering if is there any way to set up an alias on user's ~/.bash_aliases thru a Makefile.
Let's say I have a bash script called foo.sh which prints what you've passed to it. E.g.:
Input
sh foo.sh bar
Output
bar
Now, on my Makefile I want to have a something like:
install:
#echo "alias foo=sh foo.sh $#" << ~/.bash_aliases
So everytime user does make install it will automatically have the foo alias available. Then, instead of doing the last input, we would have something like:
Input
foo bar
Output
bar
Does anyone know if it's possible to do such thing?
Thanks in advance.
are you sure you want to add the same line to the user's ~/.bash_aliases everytime they run your Makefile?
and what about users who don't use bash but another shell, like zsh?
and what about other users? if the admin types make install, they usually expect the "installation" to be available to each and every user of the system, not just themselves.
if you only care about making your script foo.sh available as foo, then you probably should install a binary called foo.
install:
$(INSTALL) foo.sh $(bindir)/foo
btw, Debian policy mandates scripts to be installed without .sh extension. i think this is a hint that one generally shouldn't install with script suffixes.
What about:
install:
#echo "alias foo=foo.sh" >> ~/.bash_aliases