How to replace spaces in all file names with underscore in Linux using shell script?

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











up vote
13
down vote

favorite
8












I tried following shell script which should replace spaces from all xml filenames



for xml_file in $(find $1 -name "* .xml" -type f);
do
echo "removing spaces from XML file:" $xml_file
mv "$xml_file" "$xml_file// /_";
done


Suppose, I have xml file with the name xy z.xml, then it gives:



removing spaces from XML file: /home/krishna/test/xy
mv: cannot stat `/home/krishna/test/xy': No such file or directory
removing spaces from XML file: .xml
mv: cannot stat `z.xml': No such file or directory









share|improve this question



























    up vote
    13
    down vote

    favorite
    8












    I tried following shell script which should replace spaces from all xml filenames



    for xml_file in $(find $1 -name "* .xml" -type f);
    do
    echo "removing spaces from XML file:" $xml_file
    mv "$xml_file" "$xml_file// /_";
    done


    Suppose, I have xml file with the name xy z.xml, then it gives:



    removing spaces from XML file: /home/krishna/test/xy
    mv: cannot stat `/home/krishna/test/xy': No such file or directory
    removing spaces from XML file: .xml
    mv: cannot stat `z.xml': No such file or directory









    share|improve this question

























      up vote
      13
      down vote

      favorite
      8









      up vote
      13
      down vote

      favorite
      8






      8





      I tried following shell script which should replace spaces from all xml filenames



      for xml_file in $(find $1 -name "* .xml" -type f);
      do
      echo "removing spaces from XML file:" $xml_file
      mv "$xml_file" "$xml_file// /_";
      done


      Suppose, I have xml file with the name xy z.xml, then it gives:



      removing spaces from XML file: /home/krishna/test/xy
      mv: cannot stat `/home/krishna/test/xy': No such file or directory
      removing spaces from XML file: .xml
      mv: cannot stat `z.xml': No such file or directory









      share|improve this question















      I tried following shell script which should replace spaces from all xml filenames



      for xml_file in $(find $1 -name "* .xml" -type f);
      do
      echo "removing spaces from XML file:" $xml_file
      mv "$xml_file" "$xml_file// /_";
      done


      Suppose, I have xml file with the name xy z.xml, then it gives:



      removing spaces from XML file: /home/krishna/test/xy
      mv: cannot stat `/home/krishna/test/xy': No such file or directory
      removing spaces from XML file: .xml
      mv: cannot stat `z.xml': No such file or directory






      shell-script files find rename mv






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 11 at 20:56









      roaima

      40.6k547110




      40.6k547110










      asked Aug 14 '15 at 9:40









      krishna

      124138




      124138




















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          18
          down vote



          accepted










          Use this with bash:



          find $1 -name "* *.xml" -type f -print0 | 
          while read -d $'' f; do mv -v "$f" "$f// /_"; done


          find will search for files with a space in the name. The filenames will be printed with a nullbyte (-print0) as delimiter to also cope with special filenames.
          Then the read builtin reads the filenames delimited by the nullbyte and finally mv replaces the spaces with an underscore.



          EDIT: If you want to remove the spaces in the directories too, it's a bit more complicated. The directories are renamed and then not anymore accessible by the name find finds. Try this:



          find -name "* *" -print0 | sort -rz | 
          while read -d $'' f; do mv -v "$f" "$(dirname "$f")/$(basename "$f// /_")"; done


          The sort -rz reverses the file order, so that the deepest files in a folder are the first to move and the folder itself will be the last one. So, there are never folders renamed before all files and folder are rename inside of it. The mv command in the loop is a bit changed too. In the target name, we only remove the spaces in the basename of the file, else it wouldn't be accessible.






          share|improve this answer






















          • I am trying to replace spaces with underscore in all directory but it is giving error because after changing name that directory is not accessible.
            – krishna
            Aug 14 '15 at 11:42










          • @krishna I added an edit to my answer.
            – chaos
            Aug 14 '15 at 12:07










          • @chaos wow, just ran these two on two systems and it worked like a charm, few files and dirs not going through but it's only a few
            – somethingSomething
            Aug 14 at 5:46

















          up vote
          13
          down vote














          1. Using rename



            find . -type f -name "* *.xml" -exec rename "s/s/_/g" ;


            or with $1



            find "$1" -type f -name "* *.xml" -exec rename "s/s/_/g" ;



          2. Using mv



            find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "$0// /_"' ;


            or with $1



            find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "$0// /_"' ;






          share|improve this answer






















          • I don't know why but your given command is not working for me. It is not showing any error and output.
            – krishna
            Aug 14 '15 at 10:28










          • @krishna corrected, sorry
            – A.B.
            Aug 14 '15 at 10:49

















          up vote
          0
          down vote













          This is a method I found while facing the same problem:



          for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done


          I was writing a bash script file to automatically update my ssl certificates.






          share|improve this answer






















            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',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            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%2f223182%2fhow-to-replace-spaces-in-all-file-names-with-underscore-in-linux-using-shell-scr%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
            18
            down vote



            accepted










            Use this with bash:



            find $1 -name "* *.xml" -type f -print0 | 
            while read -d $'' f; do mv -v "$f" "$f// /_"; done


            find will search for files with a space in the name. The filenames will be printed with a nullbyte (-print0) as delimiter to also cope with special filenames.
            Then the read builtin reads the filenames delimited by the nullbyte and finally mv replaces the spaces with an underscore.



            EDIT: If you want to remove the spaces in the directories too, it's a bit more complicated. The directories are renamed and then not anymore accessible by the name find finds. Try this:



            find -name "* *" -print0 | sort -rz | 
            while read -d $'' f; do mv -v "$f" "$(dirname "$f")/$(basename "$f// /_")"; done


            The sort -rz reverses the file order, so that the deepest files in a folder are the first to move and the folder itself will be the last one. So, there are never folders renamed before all files and folder are rename inside of it. The mv command in the loop is a bit changed too. In the target name, we only remove the spaces in the basename of the file, else it wouldn't be accessible.






            share|improve this answer






















            • I am trying to replace spaces with underscore in all directory but it is giving error because after changing name that directory is not accessible.
              – krishna
              Aug 14 '15 at 11:42










            • @krishna I added an edit to my answer.
              – chaos
              Aug 14 '15 at 12:07










            • @chaos wow, just ran these two on two systems and it worked like a charm, few files and dirs not going through but it's only a few
              – somethingSomething
              Aug 14 at 5:46














            up vote
            18
            down vote



            accepted










            Use this with bash:



            find $1 -name "* *.xml" -type f -print0 | 
            while read -d $'' f; do mv -v "$f" "$f// /_"; done


            find will search for files with a space in the name. The filenames will be printed with a nullbyte (-print0) as delimiter to also cope with special filenames.
            Then the read builtin reads the filenames delimited by the nullbyte and finally mv replaces the spaces with an underscore.



            EDIT: If you want to remove the spaces in the directories too, it's a bit more complicated. The directories are renamed and then not anymore accessible by the name find finds. Try this:



            find -name "* *" -print0 | sort -rz | 
            while read -d $'' f; do mv -v "$f" "$(dirname "$f")/$(basename "$f// /_")"; done


            The sort -rz reverses the file order, so that the deepest files in a folder are the first to move and the folder itself will be the last one. So, there are never folders renamed before all files and folder are rename inside of it. The mv command in the loop is a bit changed too. In the target name, we only remove the spaces in the basename of the file, else it wouldn't be accessible.






            share|improve this answer






















            • I am trying to replace spaces with underscore in all directory but it is giving error because after changing name that directory is not accessible.
              – krishna
              Aug 14 '15 at 11:42










            • @krishna I added an edit to my answer.
              – chaos
              Aug 14 '15 at 12:07










            • @chaos wow, just ran these two on two systems and it worked like a charm, few files and dirs not going through but it's only a few
              – somethingSomething
              Aug 14 at 5:46












            up vote
            18
            down vote



            accepted







            up vote
            18
            down vote



            accepted






            Use this with bash:



            find $1 -name "* *.xml" -type f -print0 | 
            while read -d $'' f; do mv -v "$f" "$f// /_"; done


            find will search for files with a space in the name. The filenames will be printed with a nullbyte (-print0) as delimiter to also cope with special filenames.
            Then the read builtin reads the filenames delimited by the nullbyte and finally mv replaces the spaces with an underscore.



            EDIT: If you want to remove the spaces in the directories too, it's a bit more complicated. The directories are renamed and then not anymore accessible by the name find finds. Try this:



            find -name "* *" -print0 | sort -rz | 
            while read -d $'' f; do mv -v "$f" "$(dirname "$f")/$(basename "$f// /_")"; done


            The sort -rz reverses the file order, so that the deepest files in a folder are the first to move and the folder itself will be the last one. So, there are never folders renamed before all files and folder are rename inside of it. The mv command in the loop is a bit changed too. In the target name, we only remove the spaces in the basename of the file, else it wouldn't be accessible.






            share|improve this answer














            Use this with bash:



            find $1 -name "* *.xml" -type f -print0 | 
            while read -d $'' f; do mv -v "$f" "$f// /_"; done


            find will search for files with a space in the name. The filenames will be printed with a nullbyte (-print0) as delimiter to also cope with special filenames.
            Then the read builtin reads the filenames delimited by the nullbyte and finally mv replaces the spaces with an underscore.



            EDIT: If you want to remove the spaces in the directories too, it's a bit more complicated. The directories are renamed and then not anymore accessible by the name find finds. Try this:



            find -name "* *" -print0 | sort -rz | 
            while read -d $'' f; do mv -v "$f" "$(dirname "$f")/$(basename "$f// /_")"; done


            The sort -rz reverses the file order, so that the deepest files in a folder are the first to move and the folder itself will be the last one. So, there are never folders renamed before all files and folder are rename inside of it. The mv command in the loop is a bit changed too. In the target name, we only remove the spaces in the basename of the file, else it wouldn't be accessible.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Aug 14 '15 at 12:06

























            answered Aug 14 '15 at 9:50









            chaos

            34.1k770114




            34.1k770114











            • I am trying to replace spaces with underscore in all directory but it is giving error because after changing name that directory is not accessible.
              – krishna
              Aug 14 '15 at 11:42










            • @krishna I added an edit to my answer.
              – chaos
              Aug 14 '15 at 12:07










            • @chaos wow, just ran these two on two systems and it worked like a charm, few files and dirs not going through but it's only a few
              – somethingSomething
              Aug 14 at 5:46
















            • I am trying to replace spaces with underscore in all directory but it is giving error because after changing name that directory is not accessible.
              – krishna
              Aug 14 '15 at 11:42










            • @krishna I added an edit to my answer.
              – chaos
              Aug 14 '15 at 12:07










            • @chaos wow, just ran these two on two systems and it worked like a charm, few files and dirs not going through but it's only a few
              – somethingSomething
              Aug 14 at 5:46















            I am trying to replace spaces with underscore in all directory but it is giving error because after changing name that directory is not accessible.
            – krishna
            Aug 14 '15 at 11:42




            I am trying to replace spaces with underscore in all directory but it is giving error because after changing name that directory is not accessible.
            – krishna
            Aug 14 '15 at 11:42












            @krishna I added an edit to my answer.
            – chaos
            Aug 14 '15 at 12:07




            @krishna I added an edit to my answer.
            – chaos
            Aug 14 '15 at 12:07












            @chaos wow, just ran these two on two systems and it worked like a charm, few files and dirs not going through but it's only a few
            – somethingSomething
            Aug 14 at 5:46




            @chaos wow, just ran these two on two systems and it worked like a charm, few files and dirs not going through but it's only a few
            – somethingSomething
            Aug 14 at 5:46












            up vote
            13
            down vote














            1. Using rename



              find . -type f -name "* *.xml" -exec rename "s/s/_/g" ;


              or with $1



              find "$1" -type f -name "* *.xml" -exec rename "s/s/_/g" ;



            2. Using mv



              find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "$0// /_"' ;


              or with $1



              find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "$0// /_"' ;






            share|improve this answer






















            • I don't know why but your given command is not working for me. It is not showing any error and output.
              – krishna
              Aug 14 '15 at 10:28










            • @krishna corrected, sorry
              – A.B.
              Aug 14 '15 at 10:49














            up vote
            13
            down vote














            1. Using rename



              find . -type f -name "* *.xml" -exec rename "s/s/_/g" ;


              or with $1



              find "$1" -type f -name "* *.xml" -exec rename "s/s/_/g" ;



            2. Using mv



              find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "$0// /_"' ;


              or with $1



              find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "$0// /_"' ;






            share|improve this answer






















            • I don't know why but your given command is not working for me. It is not showing any error and output.
              – krishna
              Aug 14 '15 at 10:28










            • @krishna corrected, sorry
              – A.B.
              Aug 14 '15 at 10:49












            up vote
            13
            down vote










            up vote
            13
            down vote










            1. Using rename



              find . -type f -name "* *.xml" -exec rename "s/s/_/g" ;


              or with $1



              find "$1" -type f -name "* *.xml" -exec rename "s/s/_/g" ;



            2. Using mv



              find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "$0// /_"' ;


              or with $1



              find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "$0// /_"' ;






            share|improve this answer















            1. Using rename



              find . -type f -name "* *.xml" -exec rename "s/s/_/g" ;


              or with $1



              find "$1" -type f -name "* *.xml" -exec rename "s/s/_/g" ;



            2. Using mv



              find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "$0// /_"' ;


              or with $1



              find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "$0// /_"' ;







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Aug 14 '15 at 10:49

























            answered Aug 14 '15 at 9:47









            A.B.

            2,489726




            2,489726











            • I don't know why but your given command is not working for me. It is not showing any error and output.
              – krishna
              Aug 14 '15 at 10:28










            • @krishna corrected, sorry
              – A.B.
              Aug 14 '15 at 10:49
















            • I don't know why but your given command is not working for me. It is not showing any error and output.
              – krishna
              Aug 14 '15 at 10:28










            • @krishna corrected, sorry
              – A.B.
              Aug 14 '15 at 10:49















            I don't know why but your given command is not working for me. It is not showing any error and output.
            – krishna
            Aug 14 '15 at 10:28




            I don't know why but your given command is not working for me. It is not showing any error and output.
            – krishna
            Aug 14 '15 at 10:28












            @krishna corrected, sorry
            – A.B.
            Aug 14 '15 at 10:49




            @krishna corrected, sorry
            – A.B.
            Aug 14 '15 at 10:49










            up vote
            0
            down vote













            This is a method I found while facing the same problem:



            for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done


            I was writing a bash script file to automatically update my ssl certificates.






            share|improve this answer


























              up vote
              0
              down vote













              This is a method I found while facing the same problem:



              for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done


              I was writing a bash script file to automatically update my ssl certificates.






              share|improve this answer
























                up vote
                0
                down vote










                up vote
                0
                down vote









                This is a method I found while facing the same problem:



                for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done


                I was writing a bash script file to automatically update my ssl certificates.






                share|improve this answer














                This is a method I found while facing the same problem:



                for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done


                I was writing a bash script file to automatically update my ssl certificates.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 11 at 20:19









                Rui F Ribeiro

                36.8k1273117




                36.8k1273117










                answered Sep 10 at 15:21









                NekoMisaki

                4815




                4815



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f223182%2fhow-to-replace-spaces-in-all-file-names-with-underscore-in-linux-using-shell-scr%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Peggy Mitchell

                    The Forum (Inglewood, California)

                    Palaiologos