Allegro.cc - Online Community

Allegro.cc Forums » Off-Topic Ordeals » Flatten directory structure in Linux

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Flatten directory structure in Linux
Billybob
Member #3,136
January 2003

The google result for this doesn't work :(

I need to simply flatten the directory structure of some directory. Take all the files under all the directories and put them in the main directory. So:

some ->
     dir1 ->
          file1.zip
     dir2 ->
          file2.zip
     file3.zip
     file4.zip

Becomes:

flat ->
     file1.zip
     file2.zip
     file3.zip
     file4.zip
some ->
     dir1 ->
          file1.zip
     dir2 ->
          file2.zip
     file3.zip
     file4.zip

Any ideas on a command line solution? I tried:
find . -type f -name "*" | xargs -J% cp % ./test/
As suggested by an article I found on Google, but it failed with an error on xargs. Says -J is an invalid option.

Evert
Member #794
November 2000
avatar

Can't you do something like cp `find . -type f -path 'some/*'` flat/?

jhuuskon
Member #302
April 2000
avatar

for /R %I in (/some) do copy %~fI /flat
Oh, right...

But that's how would do it. ;)

You don't deserve my sig.

Billybob
Member #3,136
January 2003

Quote:

Can't you do something like cp `find . -type f -path 'some/*'` flat/?

Indeed I can!
cp `find some/*` flat/

Danke sehr!

EDIT: :( It can't handles spaces in the file names. Any way of dealing with that?

Thomas Fjellstrom
Member #476
June 2000
avatar

Re Edit: Use some proper bash maybe? :P

or learn how to use find? :P

find . -type f -path foo -exec cp '{}' flat (I think thats how find's exec works, I'd probably use the folowing version though)
or:
find . -type f -path foo | xargs -i'{}' cp '{}' flat

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Billybob
Member #3,136
January 2003

TF: That seems to work. Danke!

axilmar
Member #1,204
April 2001

In Windows you can do it with the search window: just place *.* in the filename and then move the results to the directory of your preference.

HoHo
Member #4,534
April 2004
avatar

You could do the same in Linux but that wouldn't be half as fun :)

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Billybob
Member #3,136
January 2003

Wow this is annoying:
"xargs: unmatched single quote; be default quotes are special to xargs unless you use the -0 option"

I get that error on the following command:
find ./zips/* | xargs -i'{}' cp '{}' flat
No idea what file it's choking on. It lists several directories it's omitting and then throws that errors. Some files are copied, but not all since it stops after that error.

ReyBrujo
Moderator
January 2001
avatar

find ./zips -type f -name "*.zip" -exec cp '{}' flat \;

(Edited: Added file type and name)

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

James Stanley
Member #7,275
May 2006
avatar

Quote:

In Windows you can do it with the search window: just place *.* in the filename and then move the results to the directory of your preference.

Yeah, but you couldn't have your program do it with just one call to system()... 8-)

Peter Wang
Member #23
April 2000

find with spaces:

find some -name '*.zip' -print0 | xargs -0 -i'{}' cp '{}' flat

The -print0 and -0 options use the NUL terminator as a filename separator instead of spaces.

If you were using zsh (and probably some other shells, but not bash):

cp some/**/*.zip flat

Arthur Kalliokoski
Second in Command
February 2005
avatar

Quote:

In Windows you can do it with the search window: just place *.* in the filename and then move the results to the directory of your preference.

IIRC, you can do the same by emptying the Recycle Bin (to get rid of extraneous files), then send the directory to the Recycle Bin. At least it did that 8-10 years ago when I stopped using it.

They all watch too much MSNBC... they get ideas.

BAF
Member #2,981
December 2002
avatar

What are you talking about Arthur? I don't understand what you are saying to do with the recycling bin.

HoHo
Member #4,534
April 2004
avatar

I think he deletes stuff and then uses the "restore to" command

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

CGamesPlay
Member #2,559
July 2002
avatar

Quote:

find some -name '*.zip' -print0 | xargs -0 -i'{}' cp '{}' flat

Stop the misinformation! The {} notation is special to find, not to xargs*. When find comes across a -exec, the {} is substituted with the current file. Therefore doing what you are doing will produce this command: "xargs -o i'{}' cp '{}' <list of file names>" which obviously makes no sense. In my opinion, the proper way to do this:
find some -type f | while read i; do ln -i "$i" flat/$(basename "$i); done

[edit]

  • Upon reading the xargs documentation, the -i'{}' makes the {} special to xargs.

Peter's method still won't work because it preserves directories, though.

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

kazzmir
Member #1,786
December 2001
avatar

I liked this one:

for i in `find somedir -type f`
do
  cp $i place/`basename $i`
done

CGamesPlay
Member #2,559
July 2002
avatar

Again with the not working with spaces :)

(Also cp wastes disk space)

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Kitty Cat
Member #2,815
October 2002
avatar

for i in `find somedir -type f`
do
  mv "$i" "place/`basename $i`"
done

:P

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

kazzmir
Member #1,786
December 2001
avatar

Quote:

Again with the not working with spaces :)

Oh right, forgot the space thing. Stupid bash! I guess you could put in some -print0 garbage like Rey had.

CGamesPlay
Member #2,559
July 2002
avatar

KittyCat: The for loop is splitting them, not the cp command.

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

ReyBrujo
Moderator
January 2001
avatar

Again, find . -type f -name "*.zip" -exec mv {} test \; with test being the directory where you want to put all the zip files. Easy :)

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

CGamesPlay
Member #2,559
July 2002
avatar

Quote:

find . -type f -name "*.zip" -exec mv {} test \;

Err, duh >_< The reason I didn't do that in the most recent use of this script (for me) was because I was doing something like:
find some -type f | while read i; do ln -i "$i" flat/$(echo $i | sed 's///./g'); done

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Peter Wang
Member #23
April 2000

Quote:

Peter's method still won't work because it preserves directories, though.

No, it doesn't.

Thomas Fjellstrom
Member #476
June 2000
avatar

Quote:

(Also cp wastes disk space)

cp -l is your friend ;) make a hard link.

Quote:

find some -type f | while read i; do ln -i "$i" flat/$(echo $i | sed 's///./g'); done

find some -type f | while read i; do ln -i "$i" flat/`basename $i`; done ??

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

 1   2 


Go to: