With zsh
and a mv
implementation with support for a -n
(no clobber) option, you could do:
for dir (**/unnecessary_dir_level(ND/od)) () {
(( ! $# )) || mv -n -- $@ $dir:h/ && rmdir -- $dir
} $dir/*(ND)
Where:
for var (values) cmd
is the short (and more familiar among programming languages) version of the for
loop.
**/
: a glob operator that means any level of subdirectories
N
glob qualifier: enables nullglob
for that glob (don't complain if there's no match)
D
glob qualifier: enables dotglob
for that glob (include hidden files)
/
glob qualifier: restrict to files of type directory.
od
glob qualifier: o
rder by d
epth (leaves before the branch they're on)
() { body; } args
: anonymous function with its args.
- here args being
$dir/*(ND)
: all the files including hidden ones in $dir
- the body running
mv
on those files if there are any and then rmdir
on the $dir
that should now be empty.
$dir:h
, the h
ead of $dir
(its dirname, like in csh).
Note that mv * ..
is wrong on two accounts:
- it's missing the option delimiter:
mv -- * ..
- you're missing the hidden files:
mv -- *(D) ..
in zsh, ((shopt -s nullglob failglob; exec mv -- * ..)
in bash
)
- also: you could end up losing data if there's a file with the same name in the parent.
find . -name unnecessary_dir_level -exec mv {}/* {}/.. \;
Can't work as the {}/*
glob is expanded by the shell before calling mv
. It would only be expanded to something if there was a directory called {}
in the current directory, and then move the wrong files.
You could do something similar with find
and bash
with:
find . -depth -name unnecessary_dir_level -type d -exec \
bash -O nullglob -O dotglob -c '
for dir do
set -- "$dir"/*
(( ! $# )) || mv -n -- "$@" "${dir%/*}" && rmdir -- "$dir"
done' bash {} +
myfile
both in the directory that you want to move the contents from, and in the directory that you want to move the contents to. Also "too big to back up" is something I've never seen so far, ever. – Kusalananda Jan 31 '22 at 17:47mv -u
, plus the parent folder only contains the folder to be moved from - that's why it's unnecessary; re too big - yes, you're right. the full sentence is "too big for the space I've got left on the device and the time it would take to transfer it over the network". – simone Jan 31 '22 at 17:52bash
function) that can correctly process one such directory, given the path to that directory. Once you have a solid procedure for how to process one directory, you can then simply call that function N more times, once for each of the N remaining directories. Don't worry about how to do something 1,000 times; instead, solve the question of how to do it once. Then repeat that as many times as needed. – Jim L. Jan 31 '22 at 18:01