How to move files from subdirectories that have the same directory name to its relative upper/parent directory?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
1
down vote

favorite












So, I have a directory structure like this:



parent/
├── sub1
│   └── source
│   └── file1
│ └── file2
├── sub2
│   └── sub2.1
│   └── source
│   └── something1
│ └── something2
└── sub3
└── sub3.1
└── sub3.1.1
└── source
└── other.zip


I want to move all files (with different filename) from all directories named source to its relative upper/parent directory. So, the result should be something like this:



parent2/
├── sub1
│   ├── file1
│ ├── file2
│   └── source
├── sub2
│   └── sub2.1
│   ├── something1
│ ├── something2
│   └── source
└── sub3
└── sub3.1
└── sub3.1.1
├── other.zip
└── source


Is there an easy way (one liner) to accomplish this, maybe using the find command?
Preferably one that's not too complex for me to understand. :D I'm quite new to Linux.










share|improve this question









New contributor




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























    up vote
    1
    down vote

    favorite












    So, I have a directory structure like this:



    parent/
    ├── sub1
    │   └── source
    │   └── file1
    │ └── file2
    ├── sub2
    │   └── sub2.1
    │   └── source
    │   └── something1
    │ └── something2
    └── sub3
    └── sub3.1
    └── sub3.1.1
    └── source
    └── other.zip


    I want to move all files (with different filename) from all directories named source to its relative upper/parent directory. So, the result should be something like this:



    parent2/
    ├── sub1
    │   ├── file1
    │ ├── file2
    │   └── source
    ├── sub2
    │   └── sub2.1
    │   ├── something1
    │ ├── something2
    │   └── source
    └── sub3
    └── sub3.1
    └── sub3.1.1
    ├── other.zip
    └── source


    Is there an easy way (one liner) to accomplish this, maybe using the find command?
    Preferably one that's not too complex for me to understand. :D I'm quite new to Linux.










    share|improve this question









    New contributor




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





















      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      So, I have a directory structure like this:



      parent/
      ├── sub1
      │   └── source
      │   └── file1
      │ └── file2
      ├── sub2
      │   └── sub2.1
      │   └── source
      │   └── something1
      │ └── something2
      └── sub3
      └── sub3.1
      └── sub3.1.1
      └── source
      └── other.zip


      I want to move all files (with different filename) from all directories named source to its relative upper/parent directory. So, the result should be something like this:



      parent2/
      ├── sub1
      │   ├── file1
      │ ├── file2
      │   └── source
      ├── sub2
      │   └── sub2.1
      │   ├── something1
      │ ├── something2
      │   └── source
      └── sub3
      └── sub3.1
      └── sub3.1.1
      ├── other.zip
      └── source


      Is there an easy way (one liner) to accomplish this, maybe using the find command?
      Preferably one that's not too complex for me to understand. :D I'm quite new to Linux.










      share|improve this question









      New contributor




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











      So, I have a directory structure like this:



      parent/
      ├── sub1
      │   └── source
      │   └── file1
      │ └── file2
      ├── sub2
      │   └── sub2.1
      │   └── source
      │   └── something1
      │ └── something2
      └── sub3
      └── sub3.1
      └── sub3.1.1
      └── source
      └── other.zip


      I want to move all files (with different filename) from all directories named source to its relative upper/parent directory. So, the result should be something like this:



      parent2/
      ├── sub1
      │   ├── file1
      │ ├── file2
      │   └── source
      ├── sub2
      │   └── sub2.1
      │   ├── something1
      │ ├── something2
      │   └── source
      └── sub3
      └── sub3.1
      └── sub3.1.1
      ├── other.zip
      └── source


      Is there an easy way (one liner) to accomplish this, maybe using the find command?
      Preferably one that's not too complex for me to understand. :D I'm quite new to Linux.







      command-line bash 18.04 directory






      share|improve this question









      New contributor




      Lukman Hakim 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 question









      New contributor




      Lukman Hakim 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 question




      share|improve this question








      edited 3 hours ago





















      New contributor




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









      asked 4 hours ago









      Lukman Hakim

      62




      62




      New contributor




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





      New contributor





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






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




















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          3
          down vote













          A simple for loop with the globstar option enabled (run shopt -s globstar to do that) will do the job:



          for i in ./**/source/; do
          mv "$i"* "$i%source/"
          done


          The GNU parallel Install parallel equivalent for this loop is:



          parallel mv * /// ::: ./**/source/


          Explanation




          globstar

          If set, the pattern ** used in a pathname expansion context will match all files and zero or more directories
          and subdirectories. If the pattern is followed by a /, only directories and subdirectories match.




          ./**/source/ matches every directory named source in and under the current directory, the mv command moves every file from inside the directory to its parent directory – $i%source/ is a parameter expansion which removes the string source/ from the end of the (path) string.



          Example run



          $ tree
          .
          ├── sub1
          │   └── source
          │   ├── file1
          │   └── file2
          ├── sub2
          │   └── sub2.1
          │   └── source
          │   ├── something1
          │   └── something2
          └── sub3
          └── sub3.1
          └── sub3.1.1
          └── source
          └── other.zip

          $ for i in ./**/source/; do mv "$i"* "$i%source/"; done
          $ tree
          .
          ├── sub1
          │   ├── file1
          │   ├── file2
          │   └── source
          ├── sub2
          │   └── sub2.1
          │   ├── something1
          │   ├── something2
          │   └── source
          └── sub3
          └── sub3.1
          └── sub3.1.1
          ├── other.zip
          └── source





          share|improve this answer






















          • I tried. works only in one dir `$ for i in ./**/source/; do echo "$i" ; done ./sub1/source/'
            – Vijay
            1 hour ago







          • 1




            @dessert globstar option was not enabled. Thanks.
            – Vijay
            1 hour ago

















          up vote
          0
          down vote













          You can use the below code to get what you want:



          dir=$(find . -name 'source' | sed s:source::)
          echo $dir
          for path in $dir; do
          mv "$path"source/* "$path"
          done


          The find command returns the directory path from parent to source directory. In this find . -name 'source' '.' represents the parent directory and 'source' represents the subdirectory you want to find.



          The sed command removes source from the result of find command.



          And the rest is just iteration (for) and move command (mv)






          share|improve this answer





























            up vote
            0
            down vote













            If you want a find solution, you could use this:



            find parent -name "source" -type d -exec bash -c 'cd "$1"; mv * ..' bash ;


            Explanation:




            • find parent -name "source" -type d - For each directory named source in parent...


            • -exec bash -c '...' bash ; - Call Bash with bash as $0 and the directory path as $1


            • cd "$1"; mv * .. - cd into the directory; move all its contents up one level.

              • Alternative: mv "$1"/* "$1/.."


            This is more or less based on dessert's answer.






            share|improve this answer






















              Your Answer








              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "89"
              ;
              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',
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              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
              );



              );






              Lukman Hakim is a new contributor. Be nice, and check out our Code of Conduct.









               

              draft saved


              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1089217%2fhow-to-move-files-from-subdirectories-that-have-the-same-directory-name-to-its-r%23new-answer', 'question_page');

              );

              Post as a guest






























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              3
              down vote













              A simple for loop with the globstar option enabled (run shopt -s globstar to do that) will do the job:



              for i in ./**/source/; do
              mv "$i"* "$i%source/"
              done


              The GNU parallel Install parallel equivalent for this loop is:



              parallel mv * /// ::: ./**/source/


              Explanation




              globstar

              If set, the pattern ** used in a pathname expansion context will match all files and zero or more directories
              and subdirectories. If the pattern is followed by a /, only directories and subdirectories match.




              ./**/source/ matches every directory named source in and under the current directory, the mv command moves every file from inside the directory to its parent directory – $i%source/ is a parameter expansion which removes the string source/ from the end of the (path) string.



              Example run



              $ tree
              .
              ├── sub1
              │   └── source
              │   ├── file1
              │   └── file2
              ├── sub2
              │   └── sub2.1
              │   └── source
              │   ├── something1
              │   └── something2
              └── sub3
              └── sub3.1
              └── sub3.1.1
              └── source
              └── other.zip

              $ for i in ./**/source/; do mv "$i"* "$i%source/"; done
              $ tree
              .
              ├── sub1
              │   ├── file1
              │   ├── file2
              │   └── source
              ├── sub2
              │   └── sub2.1
              │   ├── something1
              │   ├── something2
              │   └── source
              └── sub3
              └── sub3.1
              └── sub3.1.1
              ├── other.zip
              └── source





              share|improve this answer






















              • I tried. works only in one dir `$ for i in ./**/source/; do echo "$i" ; done ./sub1/source/'
                – Vijay
                1 hour ago







              • 1




                @dessert globstar option was not enabled. Thanks.
                – Vijay
                1 hour ago














              up vote
              3
              down vote













              A simple for loop with the globstar option enabled (run shopt -s globstar to do that) will do the job:



              for i in ./**/source/; do
              mv "$i"* "$i%source/"
              done


              The GNU parallel Install parallel equivalent for this loop is:



              parallel mv * /// ::: ./**/source/


              Explanation




              globstar

              If set, the pattern ** used in a pathname expansion context will match all files and zero or more directories
              and subdirectories. If the pattern is followed by a /, only directories and subdirectories match.




              ./**/source/ matches every directory named source in and under the current directory, the mv command moves every file from inside the directory to its parent directory – $i%source/ is a parameter expansion which removes the string source/ from the end of the (path) string.



              Example run



              $ tree
              .
              ├── sub1
              │   └── source
              │   ├── file1
              │   └── file2
              ├── sub2
              │   └── sub2.1
              │   └── source
              │   ├── something1
              │   └── something2
              └── sub3
              └── sub3.1
              └── sub3.1.1
              └── source
              └── other.zip

              $ for i in ./**/source/; do mv "$i"* "$i%source/"; done
              $ tree
              .
              ├── sub1
              │   ├── file1
              │   ├── file2
              │   └── source
              ├── sub2
              │   └── sub2.1
              │   ├── something1
              │   ├── something2
              │   └── source
              └── sub3
              └── sub3.1
              └── sub3.1.1
              ├── other.zip
              └── source





              share|improve this answer






















              • I tried. works only in one dir `$ for i in ./**/source/; do echo "$i" ; done ./sub1/source/'
                – Vijay
                1 hour ago







              • 1




                @dessert globstar option was not enabled. Thanks.
                – Vijay
                1 hour ago












              up vote
              3
              down vote










              up vote
              3
              down vote









              A simple for loop with the globstar option enabled (run shopt -s globstar to do that) will do the job:



              for i in ./**/source/; do
              mv "$i"* "$i%source/"
              done


              The GNU parallel Install parallel equivalent for this loop is:



              parallel mv * /// ::: ./**/source/


              Explanation




              globstar

              If set, the pattern ** used in a pathname expansion context will match all files and zero or more directories
              and subdirectories. If the pattern is followed by a /, only directories and subdirectories match.




              ./**/source/ matches every directory named source in and under the current directory, the mv command moves every file from inside the directory to its parent directory – $i%source/ is a parameter expansion which removes the string source/ from the end of the (path) string.



              Example run



              $ tree
              .
              ├── sub1
              │   └── source
              │   ├── file1
              │   └── file2
              ├── sub2
              │   └── sub2.1
              │   └── source
              │   ├── something1
              │   └── something2
              └── sub3
              └── sub3.1
              └── sub3.1.1
              └── source
              └── other.zip

              $ for i in ./**/source/; do mv "$i"* "$i%source/"; done
              $ tree
              .
              ├── sub1
              │   ├── file1
              │   ├── file2
              │   └── source
              ├── sub2
              │   └── sub2.1
              │   ├── something1
              │   ├── something2
              │   └── source
              └── sub3
              └── sub3.1
              └── sub3.1.1
              ├── other.zip
              └── source





              share|improve this answer














              A simple for loop with the globstar option enabled (run shopt -s globstar to do that) will do the job:



              for i in ./**/source/; do
              mv "$i"* "$i%source/"
              done


              The GNU parallel Install parallel equivalent for this loop is:



              parallel mv * /// ::: ./**/source/


              Explanation




              globstar

              If set, the pattern ** used in a pathname expansion context will match all files and zero or more directories
              and subdirectories. If the pattern is followed by a /, only directories and subdirectories match.




              ./**/source/ matches every directory named source in and under the current directory, the mv command moves every file from inside the directory to its parent directory – $i%source/ is a parameter expansion which removes the string source/ from the end of the (path) string.



              Example run



              $ tree
              .
              ├── sub1
              │   └── source
              │   ├── file1
              │   └── file2
              ├── sub2
              │   └── sub2.1
              │   └── source
              │   ├── something1
              │   └── something2
              └── sub3
              └── sub3.1
              └── sub3.1.1
              └── source
              └── other.zip

              $ for i in ./**/source/; do mv "$i"* "$i%source/"; done
              $ tree
              .
              ├── sub1
              │   ├── file1
              │   ├── file2
              │   └── source
              ├── sub2
              │   └── sub2.1
              │   ├── something1
              │   ├── something2
              │   └── source
              └── sub3
              └── sub3.1
              └── sub3.1.1
              ├── other.zip
              └── source






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited 1 hour ago

























              answered 3 hours ago









              dessert

              20.4k55896




              20.4k55896











              • I tried. works only in one dir `$ for i in ./**/source/; do echo "$i" ; done ./sub1/source/'
                – Vijay
                1 hour ago







              • 1




                @dessert globstar option was not enabled. Thanks.
                – Vijay
                1 hour ago
















              • I tried. works only in one dir `$ for i in ./**/source/; do echo "$i" ; done ./sub1/source/'
                – Vijay
                1 hour ago







              • 1




                @dessert globstar option was not enabled. Thanks.
                – Vijay
                1 hour ago















              I tried. works only in one dir `$ for i in ./**/source/; do echo "$i" ; done ./sub1/source/'
              – Vijay
              1 hour ago





              I tried. works only in one dir `$ for i in ./**/source/; do echo "$i" ; done ./sub1/source/'
              – Vijay
              1 hour ago





              1




              1




              @dessert globstar option was not enabled. Thanks.
              – Vijay
              1 hour ago




              @dessert globstar option was not enabled. Thanks.
              – Vijay
              1 hour ago












              up vote
              0
              down vote













              You can use the below code to get what you want:



              dir=$(find . -name 'source' | sed s:source::)
              echo $dir
              for path in $dir; do
              mv "$path"source/* "$path"
              done


              The find command returns the directory path from parent to source directory. In this find . -name 'source' '.' represents the parent directory and 'source' represents the subdirectory you want to find.



              The sed command removes source from the result of find command.



              And the rest is just iteration (for) and move command (mv)






              share|improve this answer


























                up vote
                0
                down vote













                You can use the below code to get what you want:



                dir=$(find . -name 'source' | sed s:source::)
                echo $dir
                for path in $dir; do
                mv "$path"source/* "$path"
                done


                The find command returns the directory path from parent to source directory. In this find . -name 'source' '.' represents the parent directory and 'source' represents the subdirectory you want to find.



                The sed command removes source from the result of find command.



                And the rest is just iteration (for) and move command (mv)






                share|improve this answer
























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  You can use the below code to get what you want:



                  dir=$(find . -name 'source' | sed s:source::)
                  echo $dir
                  for path in $dir; do
                  mv "$path"source/* "$path"
                  done


                  The find command returns the directory path from parent to source directory. In this find . -name 'source' '.' represents the parent directory and 'source' represents the subdirectory you want to find.



                  The sed command removes source from the result of find command.



                  And the rest is just iteration (for) and move command (mv)






                  share|improve this answer














                  You can use the below code to get what you want:



                  dir=$(find . -name 'source' | sed s:source::)
                  echo $dir
                  for path in $dir; do
                  mv "$path"source/* "$path"
                  done


                  The find command returns the directory path from parent to source directory. In this find . -name 'source' '.' represents the parent directory and 'source' represents the subdirectory you want to find.



                  The sed command removes source from the result of find command.



                  And the rest is just iteration (for) and move command (mv)







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 13 mins ago









                  wjandrea

                  7,52642257




                  7,52642257










                  answered 21 mins ago









                  Sathish Kanna

                  616




                  616




















                      up vote
                      0
                      down vote













                      If you want a find solution, you could use this:



                      find parent -name "source" -type d -exec bash -c 'cd "$1"; mv * ..' bash ;


                      Explanation:




                      • find parent -name "source" -type d - For each directory named source in parent...


                      • -exec bash -c '...' bash ; - Call Bash with bash as $0 and the directory path as $1


                      • cd "$1"; mv * .. - cd into the directory; move all its contents up one level.

                        • Alternative: mv "$1"/* "$1/.."


                      This is more or less based on dessert's answer.






                      share|improve this answer


























                        up vote
                        0
                        down vote













                        If you want a find solution, you could use this:



                        find parent -name "source" -type d -exec bash -c 'cd "$1"; mv * ..' bash ;


                        Explanation:




                        • find parent -name "source" -type d - For each directory named source in parent...


                        • -exec bash -c '...' bash ; - Call Bash with bash as $0 and the directory path as $1


                        • cd "$1"; mv * .. - cd into the directory; move all its contents up one level.

                          • Alternative: mv "$1"/* "$1/.."


                        This is more or less based on dessert's answer.






                        share|improve this answer
























                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          If you want a find solution, you could use this:



                          find parent -name "source" -type d -exec bash -c 'cd "$1"; mv * ..' bash ;


                          Explanation:




                          • find parent -name "source" -type d - For each directory named source in parent...


                          • -exec bash -c '...' bash ; - Call Bash with bash as $0 and the directory path as $1


                          • cd "$1"; mv * .. - cd into the directory; move all its contents up one level.

                            • Alternative: mv "$1"/* "$1/.."


                          This is more or less based on dessert's answer.






                          share|improve this answer














                          If you want a find solution, you could use this:



                          find parent -name "source" -type d -exec bash -c 'cd "$1"; mv * ..' bash ;


                          Explanation:




                          • find parent -name "source" -type d - For each directory named source in parent...


                          • -exec bash -c '...' bash ; - Call Bash with bash as $0 and the directory path as $1


                          • cd "$1"; mv * .. - cd into the directory; move all its contents up one level.

                            • Alternative: mv "$1"/* "$1/.."


                          This is more or less based on dessert's answer.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited 3 mins ago

























                          answered 15 mins ago









                          wjandrea

                          7,52642257




                          7,52642257




















                              Lukman Hakim is a new contributor. Be nice, and check out our Code of Conduct.









                               

                              draft saved


                              draft discarded


















                              Lukman Hakim is a new contributor. Be nice, and check out our Code of Conduct.












                              Lukman Hakim is a new contributor. Be nice, and check out our Code of Conduct.











                              Lukman Hakim is a new contributor. Be nice, and check out our Code of Conduct.













                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1089217%2fhow-to-move-files-from-subdirectories-that-have-the-same-directory-name-to-its-r%23new-answer', 'question_page');

                              );

                              Post as a guest













































































                              Comments

                              Popular posts from this blog

                              What does second last employer means? [closed]

                              Installing NextGIS Connect into QGIS 3?

                              One-line joke