3

Question

Assuming I have

dir 1/dir 2/file 1
dir 3/dir 4/file 2

(spaces in directory and file names are intentional)

I want to end up with

dir 1/file 1
dir 3/file 2

Related but incomplete answers

This answer moves all the files into the current parent directory (instead of each file's parent directory)

find . -maxdepth 1 -exec mv {} .. \;

This answer prints out each parent directory but I'm not sure how to do the moving.

find . -name '.user.log' | xargs -I{} dirname {}
nwarp
  • 133

3 Answers3

7
find -type f -execdir mv "{}" ../ \;

The -execdir is like -exec but does its job in a directory where the particular file is, so the ../ part works as you need.

To get rid of empty dir2 and dir4 in your example you need another specialized command, but the main task is done.

0

for x in */* ; do [ -d $x ] && ( echo cd $x ; echo pwd ; echo mv * .. ; echo cd ../.. ) ; done

Like what you see? Then remove the word echo (from multiple locations)

Might not work in every case, e.g. if symbolic links are used. Tested with OpenBSD ksh (preliminary results looked good on manual visual inspection -- I did not remove echo commands).

Note that [ is a command ; it shares the same man page as test (although since it is an internal command for your shell, you'd want to use the man page for your shell and search for documentation on the command.)

TOOGAM
  • 16,486
0

You're started correctly. However you can extend it a little in conjunction with the predicate -type to get just files. Using xargs and the bountiful powers of bash you have

find . -maxdepth 3 -mindepth 3 -type f |xargs -n1 bash -c 'cd $(dirname $0) ; mv $0 ..'

$0 is the positional argument passed to bash by xargs. To watch it as it happens you can use the -t option to xargs as -tn1

Note: I've limited the depth of search by using -mindepth $D and -maxdepth $D, feel free to change as per your requirements.

Note 2: Kamil's answer (using -execdir is actually a much better solution).

Samveen
  • 332