Note:
* This answer solves the OP's specific problem, in whose context "grandparent directory" means: the parent directory of the directory containing a file (it is the grandparent path from the file's perspective).
* By contrast, given the question's generic title, other answers here focus (only) on getting a directory's grandparent directory; the succinct answer to the generic question is: grandParentDir=$(cd ../..; printf %s "$PWD")
to get the full path, and grandParentDirName=$(cd ../..; basename -- "$PWD")
to get the dir. name only.
Try the following:
find . -name '*.jpg' \
-execdir bash -c \
'old="$1"; new="$(cd ..; basename -- "$PWD").${old##*.}"; echo mv "$old" "$new"' - {} \;
Note: echo
was prepended to mv
to be safe - remove it to perform the actual renaming.
-execdir ..\;
executes the specified command in the specific directory that contains a given matching file and expands{}
to the filename of each.bash -c
is used to execute a small ad-hoc script:$(cd ..; basename -- "$PWD")
determines the parent directory name of the directory containing the file, which is the grandparent path from the file's perspective.${old##*.}
is a Bash parameter expansion that returns the input filename's suffix (extension).Note how
{}
- the filename at hand - is passed as the 2nd argument to the command in order to bind to$1
, becausebash -c
uses the 1st one to set$0
(which is set to dummy value_
here).
Note that each file is merely renamed, i.e., it stays in its original directory.
Caveat:
- Each directory with a matching file should only contain 1 matching file, otherwise multiple files will be renamed to the same target name in sequence - effectively, only the last file renamed will survive.