Flattening a nested directoryHow can I use two bash commands in -exec of find command?Unnest directories that...

What are these pads?

Expl3 and recent xparse on overleaf: No expl3 loader detected

Why doesn't increasing the temperature of something like wood or paper set them on fire?

What's an appropriate age to involve kids in life changing decisions?

Names of the Six Tastes

How to avoid making self and former employee look bad when reporting on fixing former employee's work?

Why is it wrong to *implement* myself a known, published, widely believed to be secure crypto algorithm?

Employee is self-centered and affects the team negatively

Does this website provide consistent translation into Wookiee?

Align a table column at a specific symbol

Where do 5 or more U.S. counties meet in a single point?

Are there vaccine ingredients which may not be disclosed ("hidden", "trade secret", or similar)?

Is there a reason why Turkey took the Balkan territories of the Ottoman Empire, instead of Greece or another of the Balkan states?

Is the tensor product (of vector spaces) commutative?

Exactly which act of bravery are Luke and Han awarded a medal for?

As a small race with a heavy weapon, does enlage remove the disadvantage?

When an electron around an atom drops to a lower state, is 100% of the energy converted to a photon?

Opposite party turned away from voting when ballot is all opposing party

How would an instant or sorcery with an effect that targets work with Feather?

How can I test a shell script in a "safe environment" to avoid harm to my computer?

Whose birthyears are canonically established in the MCU?

How do I minimise waste on a flight?

Is there a need for better software for writers?

Why does this pattern in powers happen?



Flattening a nested directory


How can I use two bash commands in -exec of find command?Unnest directories that have same nameMove some files on every dir to a different dircopying files from one directory to anotherFind a particular nesting of directory names, e.g. …/project/dir1/dir2Flattening folder structureDoes soft linking a directory hard link its subfiles?Flattening folder structure with duplicate file namesFlattening complex folder structures with duplicate file namescreate empty files with same directory structure as reference directoryRecursively move specific files in nested directories to a name derived from the pathRemove files from directory that do not have corresponding pair in another directory based on file prefix?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







65















This is probably very simple, but I can't figure it out. I have a directory structure like this (dir2 is inside dir1):



/dir1
/dir2
|
--- file1
|
--- file2


What is the best way to 'flatten' this director structure in such a way to get file1 and file2 in dir1 not dir2.










share|improve this question

























  • askubuntu.com/questions/633945/…

    – Ferroao
    Dec 12 '17 at 14:55


















65















This is probably very simple, but I can't figure it out. I have a directory structure like this (dir2 is inside dir1):



/dir1
/dir2
|
--- file1
|
--- file2


What is the best way to 'flatten' this director structure in such a way to get file1 and file2 in dir1 not dir2.










share|improve this question

























  • askubuntu.com/questions/633945/…

    – Ferroao
    Dec 12 '17 at 14:55














65












65








65


35






This is probably very simple, but I can't figure it out. I have a directory structure like this (dir2 is inside dir1):



/dir1
/dir2
|
--- file1
|
--- file2


What is the best way to 'flatten' this director structure in such a way to get file1 and file2 in dir1 not dir2.










share|improve this question
















This is probably very simple, but I can't figure it out. I have a directory structure like this (dir2 is inside dir1):



/dir1
/dir2
|
--- file1
|
--- file2


What is the best way to 'flatten' this director structure in such a way to get file1 and file2 in dir1 not dir2.







files directory rename cp recursive






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 25 '12 at 0:01









Gilles

552k13211271637




552k13211271637










asked Oct 24 '12 at 19:28









turtleturtle

87721316




87721316













  • askubuntu.com/questions/633945/…

    – Ferroao
    Dec 12 '17 at 14:55



















  • askubuntu.com/questions/633945/…

    – Ferroao
    Dec 12 '17 at 14:55

















askubuntu.com/questions/633945/…

– Ferroao
Dec 12 '17 at 14:55





askubuntu.com/questions/633945/…

– Ferroao
Dec 12 '17 at 14:55










6 Answers
6






active

oldest

votes


















67














You can do this with GNU find and GNU mv:



find /dir1 -mindepth 2 -type f -exec mv -t /dir1 -i '{}' +


Basically, the way that works if that find goes through the entire directory tree and for each file (-type f) that is not in the top-level directory (-mindepth 2), it runs a mv to move it to the directory you want (-exec mv … +). The -t argument to mv lets you specify the destination directory first, which is needed because the + form of -exec puts all the source locations at the end of the command. The -i makes mv ask before overwriting any duplicates; you can substitute -f to overwrite them without asking (or -n to not ask or overwrite).



As Stephane Chazelas points out, the above only works with GNU tools (which are standard on Linux, but not most other systems). The following is somewhat slower (because it invokes mv multiple times) but much more universal:



find /dir1 -mindepth 2 -type f -exec mv -i '{}' /dir1 ';'





share|improve this answer





















  • 3





    Edited to use -exec + so that it doesn't execute a large number of processes of mv

    – Random832
    Oct 24 '12 at 19:32






  • 1





    @Random832 And going to revert again, because + doesn't work. mv needs the destination as the final argument, but + would have the sources as the final argument. Find wont even accept the syntax you changed it to (find: missing argument to `-exec')

    – derobert
    Oct 24 '12 at 19:34








  • 1





    @Random832 but I suppose mv has a -t we can use, so I'll change it to that.

    – derobert
    Oct 24 '12 at 19:36











  • @Random832 See How can I use two bash commands in -exec of find command?

    – Gilles
    Oct 24 '12 at 22:10






  • 1





    @Dom find prints hidden (dot) files by default. The depth is relative to the directory you pass to find.

    – derobert
    Jul 15 '13 at 15:32



















30














In zsh:



mv dir1/*/**/*(.D) dir1


**/ traverses subdirectories recursively. The glob qualifier . matches regular files only, and D ensures that dot files are included (by default, files whose name starts with a . are excluded from wildcard matches). To clean up now-empty directories afterwards, run rmdir dir1/**/*(/Dod)/ restricts to directories, and od orders the matches depth first so as to remove dir1/dir2/dir3 before dir1/dir2.



If the total length of the file names is very large, you may run into a limitation on the command line length. Zsh has builtins for mv and rmdir which are not affected by this limitation: run zmodload zsh/files to enable them.



With only POSIX tools:



find dir1 -type f -exec mv {} dir1 ;
find dir1 -depth -exec rmdir {} ;


or (faster because it doesn't have to run a separate process for each file)



find dir1 -type f -exec sh -c 'mv "$@" dir1' _ {} +
find dir1 -depth -exec rmdir {} +





share|improve this answer





















  • 1





    This should be the accepted answer! Especially with the concise zsh version.

    – Adamski
    Sep 6 '17 at 10:18





















3














Try doing this :



cp /dir1/dir2/file{1,2} /another/place


or for each files matching file[0-9]* in the subdir :



cp /dir1/dir2/file[0-9]* /another/place


See http://mywiki.wooledge.org/glob






share|improve this answer
























  • I should have indicated this, but I have to many files to use {} in my real problem.

    – turtle
    Oct 24 '12 at 19:30













  • See my second solution

    – Gilles Quenot
    Oct 24 '12 at 19:31











  • Bingo. Thanks for the help. This is definitely the best solution.

    – turtle
    Oct 24 '12 at 19:34



















2














I wrote two functions you can use together that do just that, you can limit the directory level by adding a -maxdepth $VAL parameter.



# This scripts flattens the file directory
# Run this script with a folder as parameter:
# $ path/to/script path/to/folder

#!/bin/bash

rmEmptyDirs(){
local DIR="$1"
for dir in "$DIR"/*/
do
[ -d "${dir}" ] || continue # if not a directory, skip
dir=${dir%*/}
if [ "$(ls -A "$dir")" ]; then
rmEmptyDirs "$dir"
else
rmdir "$dir"
fi
done
if [ "$(ls -A "$DIR")" ]; then
rmEmptyDirs "$DIR"
fi
}

flattenDir(){
local DIR="$1"
find "$DIR" -mindepth 2 -type f -exec mv -i '{}' "$DIR" ';'
}

read -p "Do you wish to flatten folder: ${1}? " -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
flattenDir "$1" &
rmEmptyDirs "$1" &
echo "Done";
fi





share|improve this answer


























  • Man, I just misused your script by forgetting the path argument, that just really fucked up my server. Ok, I'm the guy who copy paste things and misuse them, but guys, be wise and add checks / confirmations on scripts that delete / move stuffs like that...

    – dulgan
    Aug 1 '18 at 8:32











  • Whoops! I am sorry to hear that. Hope you have a backup... I added a confirmation for future protection.

    – Bruno
    Aug 2 '18 at 10:34











  • Thanks @Bruno that's much better this way. My server is still running flawlessly, i commented the "flatten" part to just delete empty directories recursively from (and that was my error) root, until I saw an error that made me stop running the script.

    – dulgan
    Aug 2 '18 at 14:05



















1














Expanding on the popular answer for this question, since I had a use-case for flattening a directory containing files of the same name.



dir1/
├── dir2
│ └── file
└── dir3
└── file


In this case, the -i (--interactive) option passed to mv wouldn't yield the desired result to flatten the directory structure and handle name conflicts. So it's simply replaced with --backup=t (equivalent to --backup=numbered). More documentation on the -b (--backup) option available at https://www.gnu.org/software/coreutils/manual/coreutils.html#Backup-options.



Resulting in:



find dir1/ -mindepth 2 -type f -exec mv -t dir1/ --backup=t '{}' +


Which yields:



dir1/
├── dir2
├── dir3
├── file
└── file.~1~





share|improve this answer

































    0














    tar and zip both have the ability to incorporate and then strip away a directory structure, so I was able to quickly flatten a nested directory with



    tar -cvf all.tar *



    followed by moving all.tar to a new location then



    tar -xvf all.tar --strip=4






    share|improve this answer








    New contributor



    John is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.




















      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "106"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f52814%2fflattening-a-nested-directory%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      6 Answers
      6






      active

      oldest

      votes








      6 Answers
      6






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      67














      You can do this with GNU find and GNU mv:



      find /dir1 -mindepth 2 -type f -exec mv -t /dir1 -i '{}' +


      Basically, the way that works if that find goes through the entire directory tree and for each file (-type f) that is not in the top-level directory (-mindepth 2), it runs a mv to move it to the directory you want (-exec mv … +). The -t argument to mv lets you specify the destination directory first, which is needed because the + form of -exec puts all the source locations at the end of the command. The -i makes mv ask before overwriting any duplicates; you can substitute -f to overwrite them without asking (or -n to not ask or overwrite).



      As Stephane Chazelas points out, the above only works with GNU tools (which are standard on Linux, but not most other systems). The following is somewhat slower (because it invokes mv multiple times) but much more universal:



      find /dir1 -mindepth 2 -type f -exec mv -i '{}' /dir1 ';'





      share|improve this answer





















      • 3





        Edited to use -exec + so that it doesn't execute a large number of processes of mv

        – Random832
        Oct 24 '12 at 19:32






      • 1





        @Random832 And going to revert again, because + doesn't work. mv needs the destination as the final argument, but + would have the sources as the final argument. Find wont even accept the syntax you changed it to (find: missing argument to `-exec')

        – derobert
        Oct 24 '12 at 19:34








      • 1





        @Random832 but I suppose mv has a -t we can use, so I'll change it to that.

        – derobert
        Oct 24 '12 at 19:36











      • @Random832 See How can I use two bash commands in -exec of find command?

        – Gilles
        Oct 24 '12 at 22:10






      • 1





        @Dom find prints hidden (dot) files by default. The depth is relative to the directory you pass to find.

        – derobert
        Jul 15 '13 at 15:32
















      67














      You can do this with GNU find and GNU mv:



      find /dir1 -mindepth 2 -type f -exec mv -t /dir1 -i '{}' +


      Basically, the way that works if that find goes through the entire directory tree and for each file (-type f) that is not in the top-level directory (-mindepth 2), it runs a mv to move it to the directory you want (-exec mv … +). The -t argument to mv lets you specify the destination directory first, which is needed because the + form of -exec puts all the source locations at the end of the command. The -i makes mv ask before overwriting any duplicates; you can substitute -f to overwrite them without asking (or -n to not ask or overwrite).



      As Stephane Chazelas points out, the above only works with GNU tools (which are standard on Linux, but not most other systems). The following is somewhat slower (because it invokes mv multiple times) but much more universal:



      find /dir1 -mindepth 2 -type f -exec mv -i '{}' /dir1 ';'





      share|improve this answer





















      • 3





        Edited to use -exec + so that it doesn't execute a large number of processes of mv

        – Random832
        Oct 24 '12 at 19:32






      • 1





        @Random832 And going to revert again, because + doesn't work. mv needs the destination as the final argument, but + would have the sources as the final argument. Find wont even accept the syntax you changed it to (find: missing argument to `-exec')

        – derobert
        Oct 24 '12 at 19:34








      • 1





        @Random832 but I suppose mv has a -t we can use, so I'll change it to that.

        – derobert
        Oct 24 '12 at 19:36











      • @Random832 See How can I use two bash commands in -exec of find command?

        – Gilles
        Oct 24 '12 at 22:10






      • 1





        @Dom find prints hidden (dot) files by default. The depth is relative to the directory you pass to find.

        – derobert
        Jul 15 '13 at 15:32














      67












      67








      67







      You can do this with GNU find and GNU mv:



      find /dir1 -mindepth 2 -type f -exec mv -t /dir1 -i '{}' +


      Basically, the way that works if that find goes through the entire directory tree and for each file (-type f) that is not in the top-level directory (-mindepth 2), it runs a mv to move it to the directory you want (-exec mv … +). The -t argument to mv lets you specify the destination directory first, which is needed because the + form of -exec puts all the source locations at the end of the command. The -i makes mv ask before overwriting any duplicates; you can substitute -f to overwrite them without asking (or -n to not ask or overwrite).



      As Stephane Chazelas points out, the above only works with GNU tools (which are standard on Linux, but not most other systems). The following is somewhat slower (because it invokes mv multiple times) but much more universal:



      find /dir1 -mindepth 2 -type f -exec mv -i '{}' /dir1 ';'





      share|improve this answer















      You can do this with GNU find and GNU mv:



      find /dir1 -mindepth 2 -type f -exec mv -t /dir1 -i '{}' +


      Basically, the way that works if that find goes through the entire directory tree and for each file (-type f) that is not in the top-level directory (-mindepth 2), it runs a mv to move it to the directory you want (-exec mv … +). The -t argument to mv lets you specify the destination directory first, which is needed because the + form of -exec puts all the source locations at the end of the command. The -i makes mv ask before overwriting any duplicates; you can substitute -f to overwrite them without asking (or -n to not ask or overwrite).



      As Stephane Chazelas points out, the above only works with GNU tools (which are standard on Linux, but not most other systems). The following is somewhat slower (because it invokes mv multiple times) but much more universal:



      find /dir1 -mindepth 2 -type f -exec mv -i '{}' /dir1 ';'






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 22 at 18:30

























      answered Oct 24 '12 at 19:30









      derobertderobert

      76.1k8164223




      76.1k8164223








      • 3





        Edited to use -exec + so that it doesn't execute a large number of processes of mv

        – Random832
        Oct 24 '12 at 19:32






      • 1





        @Random832 And going to revert again, because + doesn't work. mv needs the destination as the final argument, but + would have the sources as the final argument. Find wont even accept the syntax you changed it to (find: missing argument to `-exec')

        – derobert
        Oct 24 '12 at 19:34








      • 1





        @Random832 but I suppose mv has a -t we can use, so I'll change it to that.

        – derobert
        Oct 24 '12 at 19:36











      • @Random832 See How can I use two bash commands in -exec of find command?

        – Gilles
        Oct 24 '12 at 22:10






      • 1





        @Dom find prints hidden (dot) files by default. The depth is relative to the directory you pass to find.

        – derobert
        Jul 15 '13 at 15:32














      • 3





        Edited to use -exec + so that it doesn't execute a large number of processes of mv

        – Random832
        Oct 24 '12 at 19:32






      • 1





        @Random832 And going to revert again, because + doesn't work. mv needs the destination as the final argument, but + would have the sources as the final argument. Find wont even accept the syntax you changed it to (find: missing argument to `-exec')

        – derobert
        Oct 24 '12 at 19:34








      • 1





        @Random832 but I suppose mv has a -t we can use, so I'll change it to that.

        – derobert
        Oct 24 '12 at 19:36











      • @Random832 See How can I use two bash commands in -exec of find command?

        – Gilles
        Oct 24 '12 at 22:10






      • 1





        @Dom find prints hidden (dot) files by default. The depth is relative to the directory you pass to find.

        – derobert
        Jul 15 '13 at 15:32








      3




      3





      Edited to use -exec + so that it doesn't execute a large number of processes of mv

      – Random832
      Oct 24 '12 at 19:32





      Edited to use -exec + so that it doesn't execute a large number of processes of mv

      – Random832
      Oct 24 '12 at 19:32




      1




      1





      @Random832 And going to revert again, because + doesn't work. mv needs the destination as the final argument, but + would have the sources as the final argument. Find wont even accept the syntax you changed it to (find: missing argument to `-exec')

      – derobert
      Oct 24 '12 at 19:34







      @Random832 And going to revert again, because + doesn't work. mv needs the destination as the final argument, but + would have the sources as the final argument. Find wont even accept the syntax you changed it to (find: missing argument to `-exec')

      – derobert
      Oct 24 '12 at 19:34






      1




      1





      @Random832 but I suppose mv has a -t we can use, so I'll change it to that.

      – derobert
      Oct 24 '12 at 19:36





      @Random832 but I suppose mv has a -t we can use, so I'll change it to that.

      – derobert
      Oct 24 '12 at 19:36













      @Random832 See How can I use two bash commands in -exec of find command?

      – Gilles
      Oct 24 '12 at 22:10





      @Random832 See How can I use two bash commands in -exec of find command?

      – Gilles
      Oct 24 '12 at 22:10




      1




      1





      @Dom find prints hidden (dot) files by default. The depth is relative to the directory you pass to find.

      – derobert
      Jul 15 '13 at 15:32





      @Dom find prints hidden (dot) files by default. The depth is relative to the directory you pass to find.

      – derobert
      Jul 15 '13 at 15:32













      30














      In zsh:



      mv dir1/*/**/*(.D) dir1


      **/ traverses subdirectories recursively. The glob qualifier . matches regular files only, and D ensures that dot files are included (by default, files whose name starts with a . are excluded from wildcard matches). To clean up now-empty directories afterwards, run rmdir dir1/**/*(/Dod)/ restricts to directories, and od orders the matches depth first so as to remove dir1/dir2/dir3 before dir1/dir2.



      If the total length of the file names is very large, you may run into a limitation on the command line length. Zsh has builtins for mv and rmdir which are not affected by this limitation: run zmodload zsh/files to enable them.



      With only POSIX tools:



      find dir1 -type f -exec mv {} dir1 ;
      find dir1 -depth -exec rmdir {} ;


      or (faster because it doesn't have to run a separate process for each file)



      find dir1 -type f -exec sh -c 'mv "$@" dir1' _ {} +
      find dir1 -depth -exec rmdir {} +





      share|improve this answer





















      • 1





        This should be the accepted answer! Especially with the concise zsh version.

        – Adamski
        Sep 6 '17 at 10:18


















      30














      In zsh:



      mv dir1/*/**/*(.D) dir1


      **/ traverses subdirectories recursively. The glob qualifier . matches regular files only, and D ensures that dot files are included (by default, files whose name starts with a . are excluded from wildcard matches). To clean up now-empty directories afterwards, run rmdir dir1/**/*(/Dod)/ restricts to directories, and od orders the matches depth first so as to remove dir1/dir2/dir3 before dir1/dir2.



      If the total length of the file names is very large, you may run into a limitation on the command line length. Zsh has builtins for mv and rmdir which are not affected by this limitation: run zmodload zsh/files to enable them.



      With only POSIX tools:



      find dir1 -type f -exec mv {} dir1 ;
      find dir1 -depth -exec rmdir {} ;


      or (faster because it doesn't have to run a separate process for each file)



      find dir1 -type f -exec sh -c 'mv "$@" dir1' _ {} +
      find dir1 -depth -exec rmdir {} +





      share|improve this answer





















      • 1





        This should be the accepted answer! Especially with the concise zsh version.

        – Adamski
        Sep 6 '17 at 10:18
















      30












      30








      30







      In zsh:



      mv dir1/*/**/*(.D) dir1


      **/ traverses subdirectories recursively. The glob qualifier . matches regular files only, and D ensures that dot files are included (by default, files whose name starts with a . are excluded from wildcard matches). To clean up now-empty directories afterwards, run rmdir dir1/**/*(/Dod)/ restricts to directories, and od orders the matches depth first so as to remove dir1/dir2/dir3 before dir1/dir2.



      If the total length of the file names is very large, you may run into a limitation on the command line length. Zsh has builtins for mv and rmdir which are not affected by this limitation: run zmodload zsh/files to enable them.



      With only POSIX tools:



      find dir1 -type f -exec mv {} dir1 ;
      find dir1 -depth -exec rmdir {} ;


      or (faster because it doesn't have to run a separate process for each file)



      find dir1 -type f -exec sh -c 'mv "$@" dir1' _ {} +
      find dir1 -depth -exec rmdir {} +





      share|improve this answer















      In zsh:



      mv dir1/*/**/*(.D) dir1


      **/ traverses subdirectories recursively. The glob qualifier . matches regular files only, and D ensures that dot files are included (by default, files whose name starts with a . are excluded from wildcard matches). To clean up now-empty directories afterwards, run rmdir dir1/**/*(/Dod)/ restricts to directories, and od orders the matches depth first so as to remove dir1/dir2/dir3 before dir1/dir2.



      If the total length of the file names is very large, you may run into a limitation on the command line length. Zsh has builtins for mv and rmdir which are not affected by this limitation: run zmodload zsh/files to enable them.



      With only POSIX tools:



      find dir1 -type f -exec mv {} dir1 ;
      find dir1 -depth -exec rmdir {} ;


      or (faster because it doesn't have to run a separate process for each file)



      find dir1 -type f -exec sh -c 'mv "$@" dir1' _ {} +
      find dir1 -depth -exec rmdir {} +






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Oct 25 '12 at 8:54

























      answered Oct 25 '12 at 0:01









      GillesGilles

      552k13211271637




      552k13211271637








      • 1





        This should be the accepted answer! Especially with the concise zsh version.

        – Adamski
        Sep 6 '17 at 10:18
















      • 1





        This should be the accepted answer! Especially with the concise zsh version.

        – Adamski
        Sep 6 '17 at 10:18










      1




      1





      This should be the accepted answer! Especially with the concise zsh version.

      – Adamski
      Sep 6 '17 at 10:18







      This should be the accepted answer! Especially with the concise zsh version.

      – Adamski
      Sep 6 '17 at 10:18













      3














      Try doing this :



      cp /dir1/dir2/file{1,2} /another/place


      or for each files matching file[0-9]* in the subdir :



      cp /dir1/dir2/file[0-9]* /another/place


      See http://mywiki.wooledge.org/glob






      share|improve this answer
























      • I should have indicated this, but I have to many files to use {} in my real problem.

        – turtle
        Oct 24 '12 at 19:30













      • See my second solution

        – Gilles Quenot
        Oct 24 '12 at 19:31











      • Bingo. Thanks for the help. This is definitely the best solution.

        – turtle
        Oct 24 '12 at 19:34
















      3














      Try doing this :



      cp /dir1/dir2/file{1,2} /another/place


      or for each files matching file[0-9]* in the subdir :



      cp /dir1/dir2/file[0-9]* /another/place


      See http://mywiki.wooledge.org/glob






      share|improve this answer
























      • I should have indicated this, but I have to many files to use {} in my real problem.

        – turtle
        Oct 24 '12 at 19:30













      • See my second solution

        – Gilles Quenot
        Oct 24 '12 at 19:31











      • Bingo. Thanks for the help. This is definitely the best solution.

        – turtle
        Oct 24 '12 at 19:34














      3












      3








      3







      Try doing this :



      cp /dir1/dir2/file{1,2} /another/place


      or for each files matching file[0-9]* in the subdir :



      cp /dir1/dir2/file[0-9]* /another/place


      See http://mywiki.wooledge.org/glob






      share|improve this answer













      Try doing this :



      cp /dir1/dir2/file{1,2} /another/place


      or for each files matching file[0-9]* in the subdir :



      cp /dir1/dir2/file[0-9]* /another/place


      See http://mywiki.wooledge.org/glob







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Oct 24 '12 at 19:30









      Gilles QuenotGilles Quenot

      16.7k14054




      16.7k14054













      • I should have indicated this, but I have to many files to use {} in my real problem.

        – turtle
        Oct 24 '12 at 19:30













      • See my second solution

        – Gilles Quenot
        Oct 24 '12 at 19:31











      • Bingo. Thanks for the help. This is definitely the best solution.

        – turtle
        Oct 24 '12 at 19:34



















      • I should have indicated this, but I have to many files to use {} in my real problem.

        – turtle
        Oct 24 '12 at 19:30













      • See my second solution

        – Gilles Quenot
        Oct 24 '12 at 19:31











      • Bingo. Thanks for the help. This is definitely the best solution.

        – turtle
        Oct 24 '12 at 19:34

















      I should have indicated this, but I have to many files to use {} in my real problem.

      – turtle
      Oct 24 '12 at 19:30







      I should have indicated this, but I have to many files to use {} in my real problem.

      – turtle
      Oct 24 '12 at 19:30















      See my second solution

      – Gilles Quenot
      Oct 24 '12 at 19:31





      See my second solution

      – Gilles Quenot
      Oct 24 '12 at 19:31













      Bingo. Thanks for the help. This is definitely the best solution.

      – turtle
      Oct 24 '12 at 19:34





      Bingo. Thanks for the help. This is definitely the best solution.

      – turtle
      Oct 24 '12 at 19:34











      2














      I wrote two functions you can use together that do just that, you can limit the directory level by adding a -maxdepth $VAL parameter.



      # This scripts flattens the file directory
      # Run this script with a folder as parameter:
      # $ path/to/script path/to/folder

      #!/bin/bash

      rmEmptyDirs(){
      local DIR="$1"
      for dir in "$DIR"/*/
      do
      [ -d "${dir}" ] || continue # if not a directory, skip
      dir=${dir%*/}
      if [ "$(ls -A "$dir")" ]; then
      rmEmptyDirs "$dir"
      else
      rmdir "$dir"
      fi
      done
      if [ "$(ls -A "$DIR")" ]; then
      rmEmptyDirs "$DIR"
      fi
      }

      flattenDir(){
      local DIR="$1"
      find "$DIR" -mindepth 2 -type f -exec mv -i '{}' "$DIR" ';'
      }

      read -p "Do you wish to flatten folder: ${1}? " -n 1 -r
      echo # (optional) move to a new line
      if [[ $REPLY =~ ^[Yy]$ ]]
      then
      flattenDir "$1" &
      rmEmptyDirs "$1" &
      echo "Done";
      fi





      share|improve this answer


























      • Man, I just misused your script by forgetting the path argument, that just really fucked up my server. Ok, I'm the guy who copy paste things and misuse them, but guys, be wise and add checks / confirmations on scripts that delete / move stuffs like that...

        – dulgan
        Aug 1 '18 at 8:32











      • Whoops! I am sorry to hear that. Hope you have a backup... I added a confirmation for future protection.

        – Bruno
        Aug 2 '18 at 10:34











      • Thanks @Bruno that's much better this way. My server is still running flawlessly, i commented the "flatten" part to just delete empty directories recursively from (and that was my error) root, until I saw an error that made me stop running the script.

        – dulgan
        Aug 2 '18 at 14:05
















      2














      I wrote two functions you can use together that do just that, you can limit the directory level by adding a -maxdepth $VAL parameter.



      # This scripts flattens the file directory
      # Run this script with a folder as parameter:
      # $ path/to/script path/to/folder

      #!/bin/bash

      rmEmptyDirs(){
      local DIR="$1"
      for dir in "$DIR"/*/
      do
      [ -d "${dir}" ] || continue # if not a directory, skip
      dir=${dir%*/}
      if [ "$(ls -A "$dir")" ]; then
      rmEmptyDirs "$dir"
      else
      rmdir "$dir"
      fi
      done
      if [ "$(ls -A "$DIR")" ]; then
      rmEmptyDirs "$DIR"
      fi
      }

      flattenDir(){
      local DIR="$1"
      find "$DIR" -mindepth 2 -type f -exec mv -i '{}' "$DIR" ';'
      }

      read -p "Do you wish to flatten folder: ${1}? " -n 1 -r
      echo # (optional) move to a new line
      if [[ $REPLY =~ ^[Yy]$ ]]
      then
      flattenDir "$1" &
      rmEmptyDirs "$1" &
      echo "Done";
      fi





      share|improve this answer


























      • Man, I just misused your script by forgetting the path argument, that just really fucked up my server. Ok, I'm the guy who copy paste things and misuse them, but guys, be wise and add checks / confirmations on scripts that delete / move stuffs like that...

        – dulgan
        Aug 1 '18 at 8:32











      • Whoops! I am sorry to hear that. Hope you have a backup... I added a confirmation for future protection.

        – Bruno
        Aug 2 '18 at 10:34











      • Thanks @Bruno that's much better this way. My server is still running flawlessly, i commented the "flatten" part to just delete empty directories recursively from (and that was my error) root, until I saw an error that made me stop running the script.

        – dulgan
        Aug 2 '18 at 14:05














      2












      2








      2







      I wrote two functions you can use together that do just that, you can limit the directory level by adding a -maxdepth $VAL parameter.



      # This scripts flattens the file directory
      # Run this script with a folder as parameter:
      # $ path/to/script path/to/folder

      #!/bin/bash

      rmEmptyDirs(){
      local DIR="$1"
      for dir in "$DIR"/*/
      do
      [ -d "${dir}" ] || continue # if not a directory, skip
      dir=${dir%*/}
      if [ "$(ls -A "$dir")" ]; then
      rmEmptyDirs "$dir"
      else
      rmdir "$dir"
      fi
      done
      if [ "$(ls -A "$DIR")" ]; then
      rmEmptyDirs "$DIR"
      fi
      }

      flattenDir(){
      local DIR="$1"
      find "$DIR" -mindepth 2 -type f -exec mv -i '{}' "$DIR" ';'
      }

      read -p "Do you wish to flatten folder: ${1}? " -n 1 -r
      echo # (optional) move to a new line
      if [[ $REPLY =~ ^[Yy]$ ]]
      then
      flattenDir "$1" &
      rmEmptyDirs "$1" &
      echo "Done";
      fi





      share|improve this answer















      I wrote two functions you can use together that do just that, you can limit the directory level by adding a -maxdepth $VAL parameter.



      # This scripts flattens the file directory
      # Run this script with a folder as parameter:
      # $ path/to/script path/to/folder

      #!/bin/bash

      rmEmptyDirs(){
      local DIR="$1"
      for dir in "$DIR"/*/
      do
      [ -d "${dir}" ] || continue # if not a directory, skip
      dir=${dir%*/}
      if [ "$(ls -A "$dir")" ]; then
      rmEmptyDirs "$dir"
      else
      rmdir "$dir"
      fi
      done
      if [ "$(ls -A "$DIR")" ]; then
      rmEmptyDirs "$DIR"
      fi
      }

      flattenDir(){
      local DIR="$1"
      find "$DIR" -mindepth 2 -type f -exec mv -i '{}' "$DIR" ';'
      }

      read -p "Do you wish to flatten folder: ${1}? " -n 1 -r
      echo # (optional) move to a new line
      if [[ $REPLY =~ ^[Yy]$ ]]
      then
      flattenDir "$1" &
      rmEmptyDirs "$1" &
      echo "Done";
      fi






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Aug 3 '18 at 7:52

























      answered Jul 25 '16 at 1:28









      BrunoBruno

      1213




      1213













      • Man, I just misused your script by forgetting the path argument, that just really fucked up my server. Ok, I'm the guy who copy paste things and misuse them, but guys, be wise and add checks / confirmations on scripts that delete / move stuffs like that...

        – dulgan
        Aug 1 '18 at 8:32











      • Whoops! I am sorry to hear that. Hope you have a backup... I added a confirmation for future protection.

        – Bruno
        Aug 2 '18 at 10:34











      • Thanks @Bruno that's much better this way. My server is still running flawlessly, i commented the "flatten" part to just delete empty directories recursively from (and that was my error) root, until I saw an error that made me stop running the script.

        – dulgan
        Aug 2 '18 at 14:05



















      • Man, I just misused your script by forgetting the path argument, that just really fucked up my server. Ok, I'm the guy who copy paste things and misuse them, but guys, be wise and add checks / confirmations on scripts that delete / move stuffs like that...

        – dulgan
        Aug 1 '18 at 8:32











      • Whoops! I am sorry to hear that. Hope you have a backup... I added a confirmation for future protection.

        – Bruno
        Aug 2 '18 at 10:34











      • Thanks @Bruno that's much better this way. My server is still running flawlessly, i commented the "flatten" part to just delete empty directories recursively from (and that was my error) root, until I saw an error that made me stop running the script.

        – dulgan
        Aug 2 '18 at 14:05

















      Man, I just misused your script by forgetting the path argument, that just really fucked up my server. Ok, I'm the guy who copy paste things and misuse them, but guys, be wise and add checks / confirmations on scripts that delete / move stuffs like that...

      – dulgan
      Aug 1 '18 at 8:32





      Man, I just misused your script by forgetting the path argument, that just really fucked up my server. Ok, I'm the guy who copy paste things and misuse them, but guys, be wise and add checks / confirmations on scripts that delete / move stuffs like that...

      – dulgan
      Aug 1 '18 at 8:32













      Whoops! I am sorry to hear that. Hope you have a backup... I added a confirmation for future protection.

      – Bruno
      Aug 2 '18 at 10:34





      Whoops! I am sorry to hear that. Hope you have a backup... I added a confirmation for future protection.

      – Bruno
      Aug 2 '18 at 10:34













      Thanks @Bruno that's much better this way. My server is still running flawlessly, i commented the "flatten" part to just delete empty directories recursively from (and that was my error) root, until I saw an error that made me stop running the script.

      – dulgan
      Aug 2 '18 at 14:05





      Thanks @Bruno that's much better this way. My server is still running flawlessly, i commented the "flatten" part to just delete empty directories recursively from (and that was my error) root, until I saw an error that made me stop running the script.

      – dulgan
      Aug 2 '18 at 14:05











      1














      Expanding on the popular answer for this question, since I had a use-case for flattening a directory containing files of the same name.



      dir1/
      ├── dir2
      │ └── file
      └── dir3
      └── file


      In this case, the -i (--interactive) option passed to mv wouldn't yield the desired result to flatten the directory structure and handle name conflicts. So it's simply replaced with --backup=t (equivalent to --backup=numbered). More documentation on the -b (--backup) option available at https://www.gnu.org/software/coreutils/manual/coreutils.html#Backup-options.



      Resulting in:



      find dir1/ -mindepth 2 -type f -exec mv -t dir1/ --backup=t '{}' +


      Which yields:



      dir1/
      ├── dir2
      ├── dir3
      ├── file
      └── file.~1~





      share|improve this answer






























        1














        Expanding on the popular answer for this question, since I had a use-case for flattening a directory containing files of the same name.



        dir1/
        ├── dir2
        │ └── file
        └── dir3
        └── file


        In this case, the -i (--interactive) option passed to mv wouldn't yield the desired result to flatten the directory structure and handle name conflicts. So it's simply replaced with --backup=t (equivalent to --backup=numbered). More documentation on the -b (--backup) option available at https://www.gnu.org/software/coreutils/manual/coreutils.html#Backup-options.



        Resulting in:



        find dir1/ -mindepth 2 -type f -exec mv -t dir1/ --backup=t '{}' +


        Which yields:



        dir1/
        ├── dir2
        ├── dir3
        ├── file
        └── file.~1~





        share|improve this answer




























          1












          1








          1







          Expanding on the popular answer for this question, since I had a use-case for flattening a directory containing files of the same name.



          dir1/
          ├── dir2
          │ └── file
          └── dir3
          └── file


          In this case, the -i (--interactive) option passed to mv wouldn't yield the desired result to flatten the directory structure and handle name conflicts. So it's simply replaced with --backup=t (equivalent to --backup=numbered). More documentation on the -b (--backup) option available at https://www.gnu.org/software/coreutils/manual/coreutils.html#Backup-options.



          Resulting in:



          find dir1/ -mindepth 2 -type f -exec mv -t dir1/ --backup=t '{}' +


          Which yields:



          dir1/
          ├── dir2
          ├── dir3
          ├── file
          └── file.~1~





          share|improve this answer















          Expanding on the popular answer for this question, since I had a use-case for flattening a directory containing files of the same name.



          dir1/
          ├── dir2
          │ └── file
          └── dir3
          └── file


          In this case, the -i (--interactive) option passed to mv wouldn't yield the desired result to flatten the directory structure and handle name conflicts. So it's simply replaced with --backup=t (equivalent to --backup=numbered). More documentation on the -b (--backup) option available at https://www.gnu.org/software/coreutils/manual/coreutils.html#Backup-options.



          Resulting in:



          find dir1/ -mindepth 2 -type f -exec mv -t dir1/ --backup=t '{}' +


          Which yields:



          dir1/
          ├── dir2
          ├── dir3
          ├── file
          └── file.~1~






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jan 9 at 20:38

























          answered Jan 9 at 20:31









          Yann EvesYann Eves

          113




          113























              0














              tar and zip both have the ability to incorporate and then strip away a directory structure, so I was able to quickly flatten a nested directory with



              tar -cvf all.tar *



              followed by moving all.tar to a new location then



              tar -xvf all.tar --strip=4






              share|improve this answer








              New contributor



              John is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.
























                0














                tar and zip both have the ability to incorporate and then strip away a directory structure, so I was able to quickly flatten a nested directory with



                tar -cvf all.tar *



                followed by moving all.tar to a new location then



                tar -xvf all.tar --strip=4






                share|improve this answer








                New contributor



                John is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.






















                  0












                  0








                  0







                  tar and zip both have the ability to incorporate and then strip away a directory structure, so I was able to quickly flatten a nested directory with



                  tar -cvf all.tar *



                  followed by moving all.tar to a new location then



                  tar -xvf all.tar --strip=4






                  share|improve this answer








                  New contributor



                  John is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.









                  tar and zip both have the ability to incorporate and then strip away a directory structure, so I was able to quickly flatten a nested directory with



                  tar -cvf all.tar *



                  followed by moving all.tar to a new location then



                  tar -xvf all.tar --strip=4







                  share|improve this answer








                  New contributor



                  John is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.








                  share|improve this answer



                  share|improve this answer






                  New contributor



                  John is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.








                  answered 3 hours ago









                  JohnJohn

                  1




                  1




                  New contributor



                  John is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.




                  New contributor




                  John is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.
































                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Unix & Linux Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f52814%2fflattening-a-nested-directory%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Taj Mahal Inhaltsverzeichnis Aufbau | Geschichte | 350-Jahr-Feier | Heutige Bedeutung | Siehe auch |...

                      Baia Sprie Cuprins Etimologie | Istorie | Demografie | Politică și administrație | Arii naturale...

                      Nicolae Petrescu-Găină Cuprins Biografie | Opera | In memoriam | Varia | Controverse, incertitudini...