Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I am looking for a script for moving files from subdirs to the parent directory

My folder structure looks like this.

  • Inside of a folder A I have a lot of folders named 1,2,3,4,5...
  • All these folders contain 2 more folders named B and C.
  • B and C contain files that I want to move one level up, then delete folders B and C.

Thank you in advance for any help you can give me with this script

share|improve this question
2  
What have you tried so far? –  Helper Method Aug 6 '13 at 11:29
    
If i execute something like this inside folder A find -mindepth 3 -type f -print -exec mv {} . \; all files end up inside A not where i want them, inside folder 1 or folder 2 etc... –  Misa Aug 6 '13 at 11:41
add comment

4 Answers 4

You can use:

find test/*/* -type d | xargs -n1  sh -c 'echo mv -b ${0}/* "$( dirname ${0})" ";" rm -rvf ${0} '

It will just print Output on screen as below :

mv -b test/1/B/file1 test/1/B/file2 test/1/B/file3 test/1 ; rm -rvf test/1/B
mv -b test/1/C/file1 test/1/C/file2 test/1/C/file3 test/1 ; rm -rvf test/1/C
mv -b test/2/B/file1 test/2/B/file2 test/2/B/file3 test/2 ; rm -rvf test/2/B
mv -b test/2/C/file1 test/2/C/file2 test/2/C/file3 test/2 ; rm -rvf test/2/C
mv -b test/3/B/file1 test/3/B/file2 test/3/B/file3 test/3 ; rm -rvf test/3/B
mv -b test/3/C/file1 test/3/C/file2 test/3/C/file3 test/3 ; rm -rvf test/3/C
mv -b test/4/B/file1 test/4/B/file2 test/4/B/file3 test/4 ; rm -rvf test/4/B
mv -b test/4/C/file1 test/4/C/file2 test/4/C/file3 test/4 ; rm -rvf test/4/C
mv -b test/5/B/file1 test/5/B/file2 test/5/B/file3 test/5 ; rm -rvf test/5/B
mv -b test/5/C/file1 test/5/C/file2 test/5/C/file3 test/5 ; rm -rvf test/5/C

If output looks OK then you can simply append | sh at the end of that command, then it will run command which is shows in output.

share|improve this answer
add comment

The following commands will do the job:

cd /path/to/A
find -mindepth 3 -type f -execdir mv {} .. \;
find -mindepth 2 -type d -exec rm -d {} \;

See also man find for differences between -exec and -execdir actions.

share|improve this answer
    
Nice Radu. .. .. –  Rahul Patil Aug 6 '13 at 13:58
    
@RahulPatil And your answer is very elegant –  Radu Rădeanu Aug 6 '13 at 14:02
add comment

Given your directory structure, you don't need find for this -- the shell will suffice:

# the trailing slash below restricts results to directories
for dir in /path/to/A/*/; do
    mv "$dir"/[BC]/* $dir && rmdir "$dir"/[BC]
done
share|improve this answer
add comment

The second set of for loops in the script below should do what you're looking for. They're labeled...

# move files from subdirs to the parent directory

The first set creates the kind of file structure you described and there are some file listings (ls) to show what's happening.

Run the script as is from within an empty directory to verify it does what you want. Then cut out the second set of for loops and alter to use whatever directory and filename patterns you need.

The only thing unusual in this second set is the enclosure of the inner for loop inside parenthesis ( ... ). This is a convenient "bashism" that runs what's inside it in a subshell and so the cd only effects the inner for loop. If you don't want to use them, remove them and add a cd .. following the inner for loop.

#!/bin/bash

echo "
Current dir= $(pwd)
"

# populate directories
for d1 in 1 2 3
do
  for d2 in B C
  do
    mkdir -p $d1/$d2
    for f in 1 2
    do
      touch $d1/$d2/file$d2$f   # include $d2 in filename so unique when merged
    done
  done
done

echo "
ORIGINAL FILE STRUCTURE...
"
# show dirs & files recursively
ls -lR *

# move files from subdirs to the parent directory
for d1 in 1 2 3
do (                    # run in subshell so 'cd' does not change outer loop dir
  cd $d1                #   cd into dir so mv is simpler
  for d2 in B C
  do
    mv $d2/* .          #     Move files in B and C up to parent dir
    #                   #     NOTE: Files in B with same name as
    #                   #           files in C will be silently overwritten!
    rmdir $d2           #     Remove the now empty B and C dirs (OPTIONAL)
  done
)
done

echo "

FINAL FILE STRUCTURE...
"
# show dirs & files recursively
ls -lR *

echo "
Current dir= $(pwd)
"
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.