Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I'm trying to search for files with a certain extension and then move all of them up one level in the folder hierarchy.

Basically I have something like

/path/to/application/files/and/stuff/a1/nolongerneededirectory/*.*
/path/to/application/files/and/stuff/a2/nolongerneededirectory/*.*
/path/to/application/files/and/stuff/a3/nolongerneededirectory/*.*

Im trying to move them up like this:

/path/to/application/files/and/stuff/a1/*.*
/path/to/application/files/and/stuff/a2/*.*
/path/to/application/files/and/stuff/a3/*.*

Ideally it would do something like:

-bash-3.2$ find /path/to/ -name '*.txt'
output:
/path/to/directories1/test1/test1.txt
/path/to/directories2/test2/test2.txt
/path/to/directories3/test3/test3.txt

then 
mv /path/to/directories1/test1/test1.txt /path/to/directories1/test1.txt
mv /path/to/directories2/test2/test2.txt /path/to/directories2/test2.txt
mv /path/to/directories3/test3/test3.txt /path/to/directories3/test3.txt

I've been playing with different options and asking around, anyone have any ideas?

EDIT 1:

So I tried

`find /path/to/parent/dir -type f -exec mv {} .. \

but I get a Permission Denied

share|improve this question
    
well I tried this find /path/to/dir -type f -exec sh -c 'mv -i "$1" "${1%/*}"' sh {} \; but end up with this sh: bad substituion –  ideal2545 Apr 20 '12 at 18:09
    
Yeah I'm not to sure, just starting to learn scripting in the last week, could elucidate that if you have a second? –  ideal2545 Apr 20 '12 at 18:15
    
I tried an option from what you linked above, but I get a different error assuming a different OS (Solaris 10 in my case). find test -type f -exec mv {} .. \; output mv: cannot rename test/test2/test3/test.jar to ../crap.jar: Permission denied –  ideal2545 Apr 20 '12 at 18:20
    
Ah yes, I see the problem with this. So this will move the files relative to where I execute the command. What I'm actually trying to do is move the file up one level relative to the file. If that makes sense? –  ideal2545 Apr 20 '12 at 20:32
    
Ah, sorry. I read that wrong. The post I linked to will move the files to the parent directory from where you're starting. You want to move the files to their own parent directory. Deleted my comments as they are obsolete. –  slhck Apr 20 '12 at 21:10
add comment

2 Answers

If you have GNU find, you could do (modified from your example):

find /path/to -type f -execdir mv {} .. \;

but Solaris uses POSIX find as standard, which lacks this option. Sometimes the GNU tools are available (as e.g. gfind), though.

Also, the -mindepth switch would probably be very useful in this case to only return files at a given minimum directory depth.


Without GNU find, using a script instead:

#!/bin/sh
IFS='
'
for i in $(find /path/to -type f); do
    echo mv -- "${i}" "${i%/*/*}"
done

This will work unless the file names contain newlines. Run it as above first, and remove the echo if it looks OK (also see the -mindepth remark above).

share|improve this answer
    
while IFS= read -r -d '' file; do and done < <(find /path/to -type f -print0) will typically achieve the same, and it'd be completely safe, rather than for i in $(find…). –  slhck Apr 22 '12 at 21:02
    
OK, I just don't like to introduce Bashisms, but sometimes they do help. If someone wants to do the script like that, be sure to change #!/bin/sh to #!/bin/bash. –  Daniel Andersson Apr 23 '12 at 7:52
add comment

Create a script called move_to_parent.sh, make it executable.

#!/bin/bash

while [ $# -ge 1 ]
do
   parentPath=${1%/*/*};
   cp "$1" $parentPath;
   shift
done

Info on parameter substitution found here.

Here is another way of doing writing move_to_parent.sh using awk -

#!/bin/bash

while [ $# -ge 1 ]
do
   echo $1 | awk -F/ '
             {
                parentPath="";

                for(loop=2;loop<NF-1;loop++)
                {
                   parentPath=parentPath"/"$loop;
                }
                sub(/\ /, "\ ", $0);
                system("mv " $0 " " parentPath );
             }'
   shift
done

Run as follows -

find /path/to/parent/dir -iname "*.txt" | xargs  /path/to/scripts/move_to_parent.sh
share|improve this answer
    
Or (untested, beware) find /path/to/parent/dir -iname "*.txt" -exec /path/to/scripts/move_to_parent.sh '{}' '+' –  Eroen Apr 21 '12 at 16:27
    
You sure this works with files with spaces or globbing characters in their name? –  slhck Apr 22 '12 at 21:03
    
works fine with spaces –  bryan Apr 23 '12 at 1:37
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.