Firstly, that does not work as you stated. It will find only the regular file .mp3
(not all files with that extension) or, if .mp3
is a directory, recursively look inside it, finding all regular files below it. You could use -name "*.mp3"
instead to find all .mp3 regular files below your directory.
Now, the command in the answer you referred is
find A -type f -exec sh -c 'mv -i "$1" "${1%/*}/.."' sh {} \;
and is allegedly used for the "standard find
", which is the POSIX find
, not the GNU find
you probably have in your system. There are some differences between them, so let the POSIX find
manual guide us here.
The command finds regular files recursively, starting from directory A
, or, if there is no such directory, it looks for regular file A
in the current directory.
Now the complicated part. According to the manual, the -exec
option is of the form
-exec utility_name [argument ...] ;
See that sh
is used as utility_name
. sh -c
means "execute the following string", which is
mv -i "$1" "${1%/*}/.."
$1
is the found file, provided by {}
.
$0
is the second sh
(aha!), so this sh
here is really doing nothing, just a placeholder.
${1%/*}/..
means: fetch $1
, delete the shortest /*
match from the end of it (which is slash + its basename), append /..
to the result, and the final result is its parent directory! For example, A/B/Music/x.mp3
undergoes this transformation: A/B/Music/x.mp3
→ A/B/Music
→ A/B/Music/..
→ A/B
.
Therefore, at the end you got a neat POSIX way to move up that file using find
.
More on the %
symbol that showed up (and also its friend #
): https://stackoverflow.com/a/34952009
1
"Why two
– Kamil Maciorowski – 2020-02-17T22:54:13.770sh
s as well?" – Recently I have explained this (in comments) twice; and this is only "recently". Answering this part of your question would be the nth time for me (this doesn't mean you did something wrong). Therefore I created a separate question and answered it decently.