Delete all files except files with the extension pdf in a directory











up vote
48
down vote

favorite
20












I have a directory that contains the following:



x.pdf
y.zip
z.mp3
a.pdf


I want to delete all files apart from x.pdf and a.pdf. How do I do this from the terminal? There are no subdirectories so no need for any recursion.










share|improve this question




























    up vote
    48
    down vote

    favorite
    20












    I have a directory that contains the following:



    x.pdf
    y.zip
    z.mp3
    a.pdf


    I want to delete all files apart from x.pdf and a.pdf. How do I do this from the terminal? There are no subdirectories so no need for any recursion.










    share|improve this question


























      up vote
      48
      down vote

      favorite
      20









      up vote
      48
      down vote

      favorite
      20






      20





      I have a directory that contains the following:



      x.pdf
      y.zip
      z.mp3
      a.pdf


      I want to delete all files apart from x.pdf and a.pdf. How do I do this from the terminal? There are no subdirectories so no need for any recursion.










      share|improve this question















      I have a directory that contains the following:



      x.pdf
      y.zip
      z.mp3
      a.pdf


      I want to delete all files apart from x.pdf and a.pdf. How do I do this from the terminal? There are no subdirectories so no need for any recursion.







      command-line bash






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited May 18 '15 at 9:36









      lesmana

      11.6k84048




      11.6k84048










      asked Dec 1 '14 at 11:47









      Starkers

      1,15982137




      1,15982137






















          12 Answers
          12






          active

          oldest

          votes

















          up vote
          62
          down vote



          accepted










          cd <the directory you want>
          find . -type f ! -iname "*.pdf" -delete



          • The first command will take you to the directory in which you want to delete your files

          • The second command will delete all files except with those ending with .pdf in filename




          For example, if there is a directory called temp in your home folder:



          cd ~/temp


          then delete files:



          find . -type f ! -iname "*.pdf" -delete


          This will delete all files except xyz.pdf.



          You can combine these two commands to:



          find ~/temp -type f ! -iname "*.pdf" -delete




          . is the current directory. ! means to take all files except the ones with .pdf at the end. -type f selects only files, not directories. -delete means to delete it.



          NOTE: this command will delete all files (except pdf files but including hidden files) in current directory as well as in all sub-directories. ! must come before -name. simply -name will include only .pdf, while -iname will include both .pdf and .PDF



          To delete only in current directory and not in sub-directories add -maxdepth 1:



          find . -maxdepth 1 -type f ! -iname "*.pdf" -delete





          share|improve this answer























          • Thanks for the answer. Can you help me understand the syntax a little? . means "and"? ! means "except" -name signifies that you want to exclude by a name parameter and then -delete is the action to take upon finding? So it looks for everything except "*.pdf" and deletes them? Or have I misunderstood?
            – jessenorton
            Dec 1 '14 at 12:50










          • . means current directory. ! means to take all files except the one with .pdf at the end. -delete means to delete it. am i clear now ?
            – Edward Torvalds
            Dec 1 '14 at 12:57










          • @terdon Starkers said that there are no sub-directories.wait ill edit my answer to be more broad
            – Edward Torvalds
            Dec 1 '14 at 13:23










          • +1 You should have included the -maxdepth 1 parameter to begin with. Then suggest removing the parameter in case one wants to delete recursively.
            – Tulains Córdova
            Dec 2 '14 at 12:59






          • 3




            this brought to my attention that we should be using -iname instead of -name, or files with .PDF as an extension will slip through.
            – muru
            Dec 3 '14 at 17:01




















          up vote
          41
          down vote



          +100










          With bash's extended shell globbing, you could remove any files with extensions other than .pdf using



          rm -- *.!(pdf)


          As noted by @pts, the -- characters indicate the end of any command options, make the command safe in the rare case of files whose names start with a - character.



          If you want to delete files without any extension as well as those with extensions other than .pdf, then as pointed out by @DennisWilliamson you could use



          rm -- !(*.pdf)


          Extended globbing should be enabled by default, but if not you can do so using



          shopt -s extglob




          Especially if you intend to use this inside a script, it's important to note that if the expression doesn't match anything (i.e. if there are no non-pdf files in the directory), then by default the glob will be passed unexpanded to the rm command, resulting in an error like



          rm: cannot remove `*.!(pdf)': No such file or directory


          You can modify this default behaviour using the nullglob shell option, however that has its own issue. For a more thorough discussion see NullGlob - Greg's Wiki






          share|improve this answer























          • Better approach IMO.
            – Takkat
            Dec 1 '14 at 12:21










          • What about files without an extension? FWIW, in zsh it’s rm *~*.pdf
            – Emil Jeřábek
            Dec 1 '14 at 15:18






          • 1




            I would put the dot inside the parentheses.
            – Dennis Williamson
            Dec 1 '14 at 20:39






          • 4




            Ah, the asterisk should also go inside: !(*.py). Also, presumably, if the OP wants only ".pdf" files remaining, then files without extensions should also be deleted and not ignored.
            – Dennis Williamson
            Dec 1 '14 at 20:50








          • 1




            This approach is simpler and neater than the accepted answer.
            – Peter
            Dec 3 '14 at 10:31


















          up vote
          17
          down vote













          Delete to trash:



          $ cd <the directory you want>
          $ gvfs-trash !(*.pdf)


          Or via mv command (but in this way you cannot restore it from Trash since it doesn't record .trashinfo information, so this means you moved your files to a destination where it is as following).



          mv !(*.pdf) ~/.local/share/Trash/files





          share|improve this answer



















          • 6




            This approach is much safer than directly using rm.
            – Seth
            Dec 2 '14 at 20:13


















          up vote
          14
          down vote













          The easiest approach: Create another directory somewhere (if you're only deleting in one directory, not recursively, it can even be a subdirectory); move all the .pdf's there; delete everything else; move the pdf's back; delete the intermediate directory.



          Quick, easy, you can see exactly what you're doing. Just make sure the intermediate directory is on the same device as the directory you're cleaning up so that moves are renames, not copies!






          share|improve this answer



















          • 4




            +1 Again for a comment that makes sense to the novice user, that will almost certainly not result in deleting files unintentionally.
            – trognanders
            Dec 2 '14 at 18:59


















          up vote
          4
          down vote













          Use bash's GLOBIGNORE:



          GLOBIGNORE=x.pdf:a.pdf
          rm *
          unset GLOBIGNORE


          From bash's man page:




          GLOBIGNORE:

          A colon-separated list of patterns defining the set
          of filenames to be ignored by pathname expansion.




          A quick test:



          mkdir /tmp/foooooo
          cd /tmp/foooooo
          touch x.pdf y.zip z.mp3 a.pdf
          GLOBIGNORE=x.pdf:a.pdf
          ls -1 *


          Output:




          y.zip
          z.mp3





          share|improve this answer






























            up vote
            3
            down vote













            Be careful and compose: use xargs



            Here's an approach I like, because it lets me be very careful: compose a way to show just the files I want to delete, then send them to rm using xargs. For example:





            • ls shows me everything


            • ls | grep pdf shows me the files I want to keep. Hmm.


            • ls | grep -v pdf shows the opposite: all except what I want to keep. In other words, it shows the list of things I want to delete. I can confirm this before doing anything dangerous.


            • ls | grep -v pdf | xargs rm sends exactly that list to rm for deletion


            As I said, I mainly like this for the safety it provides: no accidental rm * for me. Two other advantages:




            • It's composable; you can use ls or find to get the initial list, as you prefer. You can use anything else you like in the process of narrowing that list - another grep, some awk, or whatever. If you needed to delete only files whose names contain a color, you could build it up this same way.

            • You can use each tool for its main purpose. I prefer to use find for finding and rm for removal, as opposed to having to remember that find accepts a -delete flag. And if you do this, again, you can compose alternate solutions; maybe instead of rm, you could create a trash command that moves the file to the trash (allowing "undeletion") and pipe to that instead of rm. You don't need to have find support that option, you just pipe to it.


            Update



            See comments by @pabouk for how modify this to handle some edge cases, such as line breaks in file names, filenames like my_pdfs.zip, etc.






            share|improve this answer



















            • 4




              I noticed three problems here: a) It will exclude any file containing pdf anywhere in its name. --- b) It will delete PDF files if any of the letter in the suffix are upper case. --- c) It is not a good idea to use output of ls. It will not work with file names containing newlines. Some implementations of ls replace special characters e.g. tab by ?. --- It is better to use: find -maxdepth 1 -print0. (not so short as ls :) ----- To resolve a) and b) use grep -vi '.pdf$' --- complete (but GNU only) solution: find -maxdepth 1 -print0 | grep -viz '.pdf$' | xargs -0 rm
              – pabouk
              Dec 1 '14 at 22:12








            • 1




              I understand that you meant the solution as an "interactive" process with multiple manual iterations but the checks will be hardly usable for long lists of files and the problems mentioned above could bring easy to overlook mistakes.
              – pabouk
              Dec 1 '14 at 22:22






            • 1




              @pabouk good points; the real world always complicates things, and your corrections are helpful. :) But I still think this overall approach is best. If there are too many files to visually confirm everything, you can | head -20 to at least see if it looks roughly correct, whereas if you just rm my_pattern, you have no chance to spot a big mistake.
              – Nathan Long
              Dec 2 '14 at 14:13






            • 1




              You can have find show you the files before you delete them too, leave out the -delete and just use find . -type f ! -name "*.pdf" to print to console, or pipe to less or a file. [and then pipe to xargs to rm if desired like pabouk's comments (with the -print0| ... -0 for weird filenames)]
              – Xen2050
              Dec 3 '14 at 7:26


















            up vote
            3
            down vote













            I usually solve such problems from the interactive Python interpreter:



            mic@mic ~ $ python
            >>> import os
            >>> for f in os.listdir('.'):
            ... if not f.endswith('.pdf'):
            ... os.remove(f)


            It might be longer than a one-liner with find or xargs, but it's extremely resilient, and I know exactly what it does, without having to research it first.






            share|improve this answer























            • For those who get increasingly nervous with every additional line, we could make it into one: for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
              – Jacob Vlijm
              Dec 4 '14 at 16:59












            • python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
              – mic_e
              Dec 4 '14 at 17:36












            • [os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
              – mic_e
              Dec 4 '14 at 17:37










            • nice! the second one gives me a syntax error, don't see why.
              – Jacob Vlijm
              Dec 4 '14 at 17:48










            • strange; it works with both python 3.4 and python 2.7 on my system.
              – mic_e
              Dec 4 '14 at 17:56


















            up vote
            2
            down vote













            better answer(compared to my previous answer) to this question will be by using the powerful file command.



            $ file -i abc.pdf
            abc: application/pdf; charset=binary


            now your problem:



            cd <the directory you want to search in>
            for var in ./*
            do
            if file -i "$var" | grep -q 'application/pdf;'
            then
            echo "$var"
            fi
            done


            the job of for command is give the files in current directory in the form of variable $var. if-then command outputs the names of pdf files by taking the exit status of 0 from file -i "$var" | grep -q 'application/pdf;' command, it will give exit status of 0 only if it finds pdf files.






            share|improve this answer






























              up vote
              1
              down vote













              rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')


              Warning! Better try first



              ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')





              share|improve this answer



















              • 2




                Ugh, this is flawed in so many ways: smallo.ruhr.de/award.html#ls, smallo.ruhr.de/award.html#grep, and it totally ignores file names with white space or special characters.
                – David Foerster
                Dec 3 '14 at 15:47






              • 1




                You should really use -i with grep for case-insensitive matching.
                – muru
                Dec 3 '14 at 16:17


















              up vote
              1
              down vote













              rm -i -- !(*@(a|x).pdf)


              Read as, remove all files that are not a.pdf or x.pdf.



              This works by making use of 2 extended globs, the outer !() to negate the contained glob which itself requires that the glob must match one or more of a or x patterns before the .pdf suffix. See glob#extglob.



              $ ls -a
              .dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3

              $ echo -- !(a.pdf)
              -- x.pdf y.zip z.mp3

              $ echo -- !(x.pdf)
              -- a.pdf y.zip z.mp3

              $ echo -- !(a.pdf|x.pdf)
              -- y.zip z.mp3

              $ echo -- !(@(a|x).pdf) # NOTE.that this matches the .dotfiles* as well
              -- . .. .dotfile1 .dotfile2 y.zip z.mp3

              $ echo -- !(*@(a|x).pdf) # but this doesn't
              -- y.zip z.mp3

              $ echo rm -i -- !(*@(a|x).pdf)
              rm -i -- y.zip z.mp3





              share|improve this answer






























                up vote
                1
                down vote













                portable shell way



                $ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'


                Pretty much POSIX and compatible with any Bourne-style shell ( ksh, bash, dash ). Well suited for portable scripts and when you can't use bash's extended shell globbing.



                perl:



                $ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'                                                             


                Or slightly cleaner:



                $ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'


                alternative python



                python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'





                share|improve this answer






























                  up vote
                  0
                  down vote













                  Be Careful of what you're deleting!



                  A safe way to test it before trying to delete is to test first with ls, as some uncaught behaviors could delete unwanted files. And you can do it directly outside of the directory. ls is similar to rm, so :



                  ls sub/path/to/files/!(*.pdf)


                  This will list



                  y.zip
                  z.mp3


                  And now you can see what you're deleting and can safely delete them :



                  rm sub/path/to/files/!(*.pdf)


                  And that's it. Yo can use wildcard * to be more selective like keeping only programming course documents :



                  rm sub/path/to/files/!(*programming*)





                  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
                    });


                    }
                    });














                    draft saved

                    draft discarded


















                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f555318%2fdelete-all-files-except-files-with-the-extension-pdf-in-a-directory%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown

























                    12 Answers
                    12






                    active

                    oldest

                    votes








                    12 Answers
                    12






                    active

                    oldest

                    votes









                    active

                    oldest

                    votes






                    active

                    oldest

                    votes








                    up vote
                    62
                    down vote



                    accepted










                    cd <the directory you want>
                    find . -type f ! -iname "*.pdf" -delete



                    • The first command will take you to the directory in which you want to delete your files

                    • The second command will delete all files except with those ending with .pdf in filename




                    For example, if there is a directory called temp in your home folder:



                    cd ~/temp


                    then delete files:



                    find . -type f ! -iname "*.pdf" -delete


                    This will delete all files except xyz.pdf.



                    You can combine these two commands to:



                    find ~/temp -type f ! -iname "*.pdf" -delete




                    . is the current directory. ! means to take all files except the ones with .pdf at the end. -type f selects only files, not directories. -delete means to delete it.



                    NOTE: this command will delete all files (except pdf files but including hidden files) in current directory as well as in all sub-directories. ! must come before -name. simply -name will include only .pdf, while -iname will include both .pdf and .PDF



                    To delete only in current directory and not in sub-directories add -maxdepth 1:



                    find . -maxdepth 1 -type f ! -iname "*.pdf" -delete





                    share|improve this answer























                    • Thanks for the answer. Can you help me understand the syntax a little? . means "and"? ! means "except" -name signifies that you want to exclude by a name parameter and then -delete is the action to take upon finding? So it looks for everything except "*.pdf" and deletes them? Or have I misunderstood?
                      – jessenorton
                      Dec 1 '14 at 12:50










                    • . means current directory. ! means to take all files except the one with .pdf at the end. -delete means to delete it. am i clear now ?
                      – Edward Torvalds
                      Dec 1 '14 at 12:57










                    • @terdon Starkers said that there are no sub-directories.wait ill edit my answer to be more broad
                      – Edward Torvalds
                      Dec 1 '14 at 13:23










                    • +1 You should have included the -maxdepth 1 parameter to begin with. Then suggest removing the parameter in case one wants to delete recursively.
                      – Tulains Córdova
                      Dec 2 '14 at 12:59






                    • 3




                      this brought to my attention that we should be using -iname instead of -name, or files with .PDF as an extension will slip through.
                      – muru
                      Dec 3 '14 at 17:01

















                    up vote
                    62
                    down vote



                    accepted










                    cd <the directory you want>
                    find . -type f ! -iname "*.pdf" -delete



                    • The first command will take you to the directory in which you want to delete your files

                    • The second command will delete all files except with those ending with .pdf in filename




                    For example, if there is a directory called temp in your home folder:



                    cd ~/temp


                    then delete files:



                    find . -type f ! -iname "*.pdf" -delete


                    This will delete all files except xyz.pdf.



                    You can combine these two commands to:



                    find ~/temp -type f ! -iname "*.pdf" -delete




                    . is the current directory. ! means to take all files except the ones with .pdf at the end. -type f selects only files, not directories. -delete means to delete it.



                    NOTE: this command will delete all files (except pdf files but including hidden files) in current directory as well as in all sub-directories. ! must come before -name. simply -name will include only .pdf, while -iname will include both .pdf and .PDF



                    To delete only in current directory and not in sub-directories add -maxdepth 1:



                    find . -maxdepth 1 -type f ! -iname "*.pdf" -delete





                    share|improve this answer























                    • Thanks for the answer. Can you help me understand the syntax a little? . means "and"? ! means "except" -name signifies that you want to exclude by a name parameter and then -delete is the action to take upon finding? So it looks for everything except "*.pdf" and deletes them? Or have I misunderstood?
                      – jessenorton
                      Dec 1 '14 at 12:50










                    • . means current directory. ! means to take all files except the one with .pdf at the end. -delete means to delete it. am i clear now ?
                      – Edward Torvalds
                      Dec 1 '14 at 12:57










                    • @terdon Starkers said that there are no sub-directories.wait ill edit my answer to be more broad
                      – Edward Torvalds
                      Dec 1 '14 at 13:23










                    • +1 You should have included the -maxdepth 1 parameter to begin with. Then suggest removing the parameter in case one wants to delete recursively.
                      – Tulains Córdova
                      Dec 2 '14 at 12:59






                    • 3




                      this brought to my attention that we should be using -iname instead of -name, or files with .PDF as an extension will slip through.
                      – muru
                      Dec 3 '14 at 17:01















                    up vote
                    62
                    down vote



                    accepted







                    up vote
                    62
                    down vote



                    accepted






                    cd <the directory you want>
                    find . -type f ! -iname "*.pdf" -delete



                    • The first command will take you to the directory in which you want to delete your files

                    • The second command will delete all files except with those ending with .pdf in filename




                    For example, if there is a directory called temp in your home folder:



                    cd ~/temp


                    then delete files:



                    find . -type f ! -iname "*.pdf" -delete


                    This will delete all files except xyz.pdf.



                    You can combine these two commands to:



                    find ~/temp -type f ! -iname "*.pdf" -delete




                    . is the current directory. ! means to take all files except the ones with .pdf at the end. -type f selects only files, not directories. -delete means to delete it.



                    NOTE: this command will delete all files (except pdf files but including hidden files) in current directory as well as in all sub-directories. ! must come before -name. simply -name will include only .pdf, while -iname will include both .pdf and .PDF



                    To delete only in current directory and not in sub-directories add -maxdepth 1:



                    find . -maxdepth 1 -type f ! -iname "*.pdf" -delete





                    share|improve this answer














                    cd <the directory you want>
                    find . -type f ! -iname "*.pdf" -delete



                    • The first command will take you to the directory in which you want to delete your files

                    • The second command will delete all files except with those ending with .pdf in filename




                    For example, if there is a directory called temp in your home folder:



                    cd ~/temp


                    then delete files:



                    find . -type f ! -iname "*.pdf" -delete


                    This will delete all files except xyz.pdf.



                    You can combine these two commands to:



                    find ~/temp -type f ! -iname "*.pdf" -delete




                    . is the current directory. ! means to take all files except the ones with .pdf at the end. -type f selects only files, not directories. -delete means to delete it.



                    NOTE: this command will delete all files (except pdf files but including hidden files) in current directory as well as in all sub-directories. ! must come before -name. simply -name will include only .pdf, while -iname will include both .pdf and .PDF



                    To delete only in current directory and not in sub-directories add -maxdepth 1:



                    find . -maxdepth 1 -type f ! -iname "*.pdf" -delete






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Dec 3 '14 at 17:19

























                    answered Dec 1 '14 at 11:51









                    Edward Torvalds

                    5,01973978




                    5,01973978












                    • Thanks for the answer. Can you help me understand the syntax a little? . means "and"? ! means "except" -name signifies that you want to exclude by a name parameter and then -delete is the action to take upon finding? So it looks for everything except "*.pdf" and deletes them? Or have I misunderstood?
                      – jessenorton
                      Dec 1 '14 at 12:50










                    • . means current directory. ! means to take all files except the one with .pdf at the end. -delete means to delete it. am i clear now ?
                      – Edward Torvalds
                      Dec 1 '14 at 12:57










                    • @terdon Starkers said that there are no sub-directories.wait ill edit my answer to be more broad
                      – Edward Torvalds
                      Dec 1 '14 at 13:23










                    • +1 You should have included the -maxdepth 1 parameter to begin with. Then suggest removing the parameter in case one wants to delete recursively.
                      – Tulains Córdova
                      Dec 2 '14 at 12:59






                    • 3




                      this brought to my attention that we should be using -iname instead of -name, or files with .PDF as an extension will slip through.
                      – muru
                      Dec 3 '14 at 17:01




















                    • Thanks for the answer. Can you help me understand the syntax a little? . means "and"? ! means "except" -name signifies that you want to exclude by a name parameter and then -delete is the action to take upon finding? So it looks for everything except "*.pdf" and deletes them? Or have I misunderstood?
                      – jessenorton
                      Dec 1 '14 at 12:50










                    • . means current directory. ! means to take all files except the one with .pdf at the end. -delete means to delete it. am i clear now ?
                      – Edward Torvalds
                      Dec 1 '14 at 12:57










                    • @terdon Starkers said that there are no sub-directories.wait ill edit my answer to be more broad
                      – Edward Torvalds
                      Dec 1 '14 at 13:23










                    • +1 You should have included the -maxdepth 1 parameter to begin with. Then suggest removing the parameter in case one wants to delete recursively.
                      – Tulains Córdova
                      Dec 2 '14 at 12:59






                    • 3




                      this brought to my attention that we should be using -iname instead of -name, or files with .PDF as an extension will slip through.
                      – muru
                      Dec 3 '14 at 17:01


















                    Thanks for the answer. Can you help me understand the syntax a little? . means "and"? ! means "except" -name signifies that you want to exclude by a name parameter and then -delete is the action to take upon finding? So it looks for everything except "*.pdf" and deletes them? Or have I misunderstood?
                    – jessenorton
                    Dec 1 '14 at 12:50




                    Thanks for the answer. Can you help me understand the syntax a little? . means "and"? ! means "except" -name signifies that you want to exclude by a name parameter and then -delete is the action to take upon finding? So it looks for everything except "*.pdf" and deletes them? Or have I misunderstood?
                    – jessenorton
                    Dec 1 '14 at 12:50












                    . means current directory. ! means to take all files except the one with .pdf at the end. -delete means to delete it. am i clear now ?
                    – Edward Torvalds
                    Dec 1 '14 at 12:57




                    . means current directory. ! means to take all files except the one with .pdf at the end. -delete means to delete it. am i clear now ?
                    – Edward Torvalds
                    Dec 1 '14 at 12:57












                    @terdon Starkers said that there are no sub-directories.wait ill edit my answer to be more broad
                    – Edward Torvalds
                    Dec 1 '14 at 13:23




                    @terdon Starkers said that there are no sub-directories.wait ill edit my answer to be more broad
                    – Edward Torvalds
                    Dec 1 '14 at 13:23












                    +1 You should have included the -maxdepth 1 parameter to begin with. Then suggest removing the parameter in case one wants to delete recursively.
                    – Tulains Córdova
                    Dec 2 '14 at 12:59




                    +1 You should have included the -maxdepth 1 parameter to begin with. Then suggest removing the parameter in case one wants to delete recursively.
                    – Tulains Córdova
                    Dec 2 '14 at 12:59




                    3




                    3




                    this brought to my attention that we should be using -iname instead of -name, or files with .PDF as an extension will slip through.
                    – muru
                    Dec 3 '14 at 17:01






                    this brought to my attention that we should be using -iname instead of -name, or files with .PDF as an extension will slip through.
                    – muru
                    Dec 3 '14 at 17:01














                    up vote
                    41
                    down vote



                    +100










                    With bash's extended shell globbing, you could remove any files with extensions other than .pdf using



                    rm -- *.!(pdf)


                    As noted by @pts, the -- characters indicate the end of any command options, make the command safe in the rare case of files whose names start with a - character.



                    If you want to delete files without any extension as well as those with extensions other than .pdf, then as pointed out by @DennisWilliamson you could use



                    rm -- !(*.pdf)


                    Extended globbing should be enabled by default, but if not you can do so using



                    shopt -s extglob




                    Especially if you intend to use this inside a script, it's important to note that if the expression doesn't match anything (i.e. if there are no non-pdf files in the directory), then by default the glob will be passed unexpanded to the rm command, resulting in an error like



                    rm: cannot remove `*.!(pdf)': No such file or directory


                    You can modify this default behaviour using the nullglob shell option, however that has its own issue. For a more thorough discussion see NullGlob - Greg's Wiki






                    share|improve this answer























                    • Better approach IMO.
                      – Takkat
                      Dec 1 '14 at 12:21










                    • What about files without an extension? FWIW, in zsh it’s rm *~*.pdf
                      – Emil Jeřábek
                      Dec 1 '14 at 15:18






                    • 1




                      I would put the dot inside the parentheses.
                      – Dennis Williamson
                      Dec 1 '14 at 20:39






                    • 4




                      Ah, the asterisk should also go inside: !(*.py). Also, presumably, if the OP wants only ".pdf" files remaining, then files without extensions should also be deleted and not ignored.
                      – Dennis Williamson
                      Dec 1 '14 at 20:50








                    • 1




                      This approach is simpler and neater than the accepted answer.
                      – Peter
                      Dec 3 '14 at 10:31















                    up vote
                    41
                    down vote



                    +100










                    With bash's extended shell globbing, you could remove any files with extensions other than .pdf using



                    rm -- *.!(pdf)


                    As noted by @pts, the -- characters indicate the end of any command options, make the command safe in the rare case of files whose names start with a - character.



                    If you want to delete files without any extension as well as those with extensions other than .pdf, then as pointed out by @DennisWilliamson you could use



                    rm -- !(*.pdf)


                    Extended globbing should be enabled by default, but if not you can do so using



                    shopt -s extglob




                    Especially if you intend to use this inside a script, it's important to note that if the expression doesn't match anything (i.e. if there are no non-pdf files in the directory), then by default the glob will be passed unexpanded to the rm command, resulting in an error like



                    rm: cannot remove `*.!(pdf)': No such file or directory


                    You can modify this default behaviour using the nullglob shell option, however that has its own issue. For a more thorough discussion see NullGlob - Greg's Wiki






                    share|improve this answer























                    • Better approach IMO.
                      – Takkat
                      Dec 1 '14 at 12:21










                    • What about files without an extension? FWIW, in zsh it’s rm *~*.pdf
                      – Emil Jeřábek
                      Dec 1 '14 at 15:18






                    • 1




                      I would put the dot inside the parentheses.
                      – Dennis Williamson
                      Dec 1 '14 at 20:39






                    • 4




                      Ah, the asterisk should also go inside: !(*.py). Also, presumably, if the OP wants only ".pdf" files remaining, then files without extensions should also be deleted and not ignored.
                      – Dennis Williamson
                      Dec 1 '14 at 20:50








                    • 1




                      This approach is simpler and neater than the accepted answer.
                      – Peter
                      Dec 3 '14 at 10:31













                    up vote
                    41
                    down vote



                    +100







                    up vote
                    41
                    down vote



                    +100




                    +100




                    With bash's extended shell globbing, you could remove any files with extensions other than .pdf using



                    rm -- *.!(pdf)


                    As noted by @pts, the -- characters indicate the end of any command options, make the command safe in the rare case of files whose names start with a - character.



                    If you want to delete files without any extension as well as those with extensions other than .pdf, then as pointed out by @DennisWilliamson you could use



                    rm -- !(*.pdf)


                    Extended globbing should be enabled by default, but if not you can do so using



                    shopt -s extglob




                    Especially if you intend to use this inside a script, it's important to note that if the expression doesn't match anything (i.e. if there are no non-pdf files in the directory), then by default the glob will be passed unexpanded to the rm command, resulting in an error like



                    rm: cannot remove `*.!(pdf)': No such file or directory


                    You can modify this default behaviour using the nullglob shell option, however that has its own issue. For a more thorough discussion see NullGlob - Greg's Wiki






                    share|improve this answer














                    With bash's extended shell globbing, you could remove any files with extensions other than .pdf using



                    rm -- *.!(pdf)


                    As noted by @pts, the -- characters indicate the end of any command options, make the command safe in the rare case of files whose names start with a - character.



                    If you want to delete files without any extension as well as those with extensions other than .pdf, then as pointed out by @DennisWilliamson you could use



                    rm -- !(*.pdf)


                    Extended globbing should be enabled by default, but if not you can do so using



                    shopt -s extglob




                    Especially if you intend to use this inside a script, it's important to note that if the expression doesn't match anything (i.e. if there are no non-pdf files in the directory), then by default the glob will be passed unexpanded to the rm command, resulting in an error like



                    rm: cannot remove `*.!(pdf)': No such file or directory


                    You can modify this default behaviour using the nullglob shell option, however that has its own issue. For a more thorough discussion see NullGlob - Greg's Wiki







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Dec 5 '14 at 1:23

























                    answered Dec 1 '14 at 12:11









                    steeldriver

                    65.1k11104176




                    65.1k11104176












                    • Better approach IMO.
                      – Takkat
                      Dec 1 '14 at 12:21










                    • What about files without an extension? FWIW, in zsh it’s rm *~*.pdf
                      – Emil Jeřábek
                      Dec 1 '14 at 15:18






                    • 1




                      I would put the dot inside the parentheses.
                      – Dennis Williamson
                      Dec 1 '14 at 20:39






                    • 4




                      Ah, the asterisk should also go inside: !(*.py). Also, presumably, if the OP wants only ".pdf" files remaining, then files without extensions should also be deleted and not ignored.
                      – Dennis Williamson
                      Dec 1 '14 at 20:50








                    • 1




                      This approach is simpler and neater than the accepted answer.
                      – Peter
                      Dec 3 '14 at 10:31


















                    • Better approach IMO.
                      – Takkat
                      Dec 1 '14 at 12:21










                    • What about files without an extension? FWIW, in zsh it’s rm *~*.pdf
                      – Emil Jeřábek
                      Dec 1 '14 at 15:18






                    • 1




                      I would put the dot inside the parentheses.
                      – Dennis Williamson
                      Dec 1 '14 at 20:39






                    • 4




                      Ah, the asterisk should also go inside: !(*.py). Also, presumably, if the OP wants only ".pdf" files remaining, then files without extensions should also be deleted and not ignored.
                      – Dennis Williamson
                      Dec 1 '14 at 20:50








                    • 1




                      This approach is simpler and neater than the accepted answer.
                      – Peter
                      Dec 3 '14 at 10:31
















                    Better approach IMO.
                    – Takkat
                    Dec 1 '14 at 12:21




                    Better approach IMO.
                    – Takkat
                    Dec 1 '14 at 12:21












                    What about files without an extension? FWIW, in zsh it’s rm *~*.pdf
                    – Emil Jeřábek
                    Dec 1 '14 at 15:18




                    What about files without an extension? FWIW, in zsh it’s rm *~*.pdf
                    – Emil Jeřábek
                    Dec 1 '14 at 15:18




                    1




                    1




                    I would put the dot inside the parentheses.
                    – Dennis Williamson
                    Dec 1 '14 at 20:39




                    I would put the dot inside the parentheses.
                    – Dennis Williamson
                    Dec 1 '14 at 20:39




                    4




                    4




                    Ah, the asterisk should also go inside: !(*.py). Also, presumably, if the OP wants only ".pdf" files remaining, then files without extensions should also be deleted and not ignored.
                    – Dennis Williamson
                    Dec 1 '14 at 20:50






                    Ah, the asterisk should also go inside: !(*.py). Also, presumably, if the OP wants only ".pdf" files remaining, then files without extensions should also be deleted and not ignored.
                    – Dennis Williamson
                    Dec 1 '14 at 20:50






                    1




                    1




                    This approach is simpler and neater than the accepted answer.
                    – Peter
                    Dec 3 '14 at 10:31




                    This approach is simpler and neater than the accepted answer.
                    – Peter
                    Dec 3 '14 at 10:31










                    up vote
                    17
                    down vote













                    Delete to trash:



                    $ cd <the directory you want>
                    $ gvfs-trash !(*.pdf)


                    Or via mv command (but in this way you cannot restore it from Trash since it doesn't record .trashinfo information, so this means you moved your files to a destination where it is as following).



                    mv !(*.pdf) ~/.local/share/Trash/files





                    share|improve this answer



















                    • 6




                      This approach is much safer than directly using rm.
                      – Seth
                      Dec 2 '14 at 20:13















                    up vote
                    17
                    down vote













                    Delete to trash:



                    $ cd <the directory you want>
                    $ gvfs-trash !(*.pdf)


                    Or via mv command (but in this way you cannot restore it from Trash since it doesn't record .trashinfo information, so this means you moved your files to a destination where it is as following).



                    mv !(*.pdf) ~/.local/share/Trash/files





                    share|improve this answer



















                    • 6




                      This approach is much safer than directly using rm.
                      – Seth
                      Dec 2 '14 at 20:13













                    up vote
                    17
                    down vote










                    up vote
                    17
                    down vote









                    Delete to trash:



                    $ cd <the directory you want>
                    $ gvfs-trash !(*.pdf)


                    Or via mv command (but in this way you cannot restore it from Trash since it doesn't record .trashinfo information, so this means you moved your files to a destination where it is as following).



                    mv !(*.pdf) ~/.local/share/Trash/files





                    share|improve this answer














                    Delete to trash:



                    $ cd <the directory you want>
                    $ gvfs-trash !(*.pdf)


                    Or via mv command (but in this way you cannot restore it from Trash since it doesn't record .trashinfo information, so this means you moved your files to a destination where it is as following).



                    mv !(*.pdf) ~/.local/share/Trash/files






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 8 '17 at 7:25

























                    answered Dec 1 '14 at 16:09









                    αғsнιη

                    24.1k2294155




                    24.1k2294155








                    • 6




                      This approach is much safer than directly using rm.
                      – Seth
                      Dec 2 '14 at 20:13














                    • 6




                      This approach is much safer than directly using rm.
                      – Seth
                      Dec 2 '14 at 20:13








                    6




                    6




                    This approach is much safer than directly using rm.
                    – Seth
                    Dec 2 '14 at 20:13




                    This approach is much safer than directly using rm.
                    – Seth
                    Dec 2 '14 at 20:13










                    up vote
                    14
                    down vote













                    The easiest approach: Create another directory somewhere (if you're only deleting in one directory, not recursively, it can even be a subdirectory); move all the .pdf's there; delete everything else; move the pdf's back; delete the intermediate directory.



                    Quick, easy, you can see exactly what you're doing. Just make sure the intermediate directory is on the same device as the directory you're cleaning up so that moves are renames, not copies!






                    share|improve this answer



















                    • 4




                      +1 Again for a comment that makes sense to the novice user, that will almost certainly not result in deleting files unintentionally.
                      – trognanders
                      Dec 2 '14 at 18:59















                    up vote
                    14
                    down vote













                    The easiest approach: Create another directory somewhere (if you're only deleting in one directory, not recursively, it can even be a subdirectory); move all the .pdf's there; delete everything else; move the pdf's back; delete the intermediate directory.



                    Quick, easy, you can see exactly what you're doing. Just make sure the intermediate directory is on the same device as the directory you're cleaning up so that moves are renames, not copies!






                    share|improve this answer



















                    • 4




                      +1 Again for a comment that makes sense to the novice user, that will almost certainly not result in deleting files unintentionally.
                      – trognanders
                      Dec 2 '14 at 18:59













                    up vote
                    14
                    down vote










                    up vote
                    14
                    down vote









                    The easiest approach: Create another directory somewhere (if you're only deleting in one directory, not recursively, it can even be a subdirectory); move all the .pdf's there; delete everything else; move the pdf's back; delete the intermediate directory.



                    Quick, easy, you can see exactly what you're doing. Just make sure the intermediate directory is on the same device as the directory you're cleaning up so that moves are renames, not copies!






                    share|improve this answer














                    The easiest approach: Create another directory somewhere (if you're only deleting in one directory, not recursively, it can even be a subdirectory); move all the .pdf's there; delete everything else; move the pdf's back; delete the intermediate directory.



                    Quick, easy, you can see exactly what you're doing. Just make sure the intermediate directory is on the same device as the directory you're cleaning up so that moves are renames, not copies!







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Dec 1 '14 at 18:26









                    David Richerby

                    29439




                    29439










                    answered Dec 1 '14 at 15:45









                    Jerry

                    1412




                    1412








                    • 4




                      +1 Again for a comment that makes sense to the novice user, that will almost certainly not result in deleting files unintentionally.
                      – trognanders
                      Dec 2 '14 at 18:59














                    • 4




                      +1 Again for a comment that makes sense to the novice user, that will almost certainly not result in deleting files unintentionally.
                      – trognanders
                      Dec 2 '14 at 18:59








                    4




                    4




                    +1 Again for a comment that makes sense to the novice user, that will almost certainly not result in deleting files unintentionally.
                    – trognanders
                    Dec 2 '14 at 18:59




                    +1 Again for a comment that makes sense to the novice user, that will almost certainly not result in deleting files unintentionally.
                    – trognanders
                    Dec 2 '14 at 18:59










                    up vote
                    4
                    down vote













                    Use bash's GLOBIGNORE:



                    GLOBIGNORE=x.pdf:a.pdf
                    rm *
                    unset GLOBIGNORE


                    From bash's man page:




                    GLOBIGNORE:

                    A colon-separated list of patterns defining the set
                    of filenames to be ignored by pathname expansion.




                    A quick test:



                    mkdir /tmp/foooooo
                    cd /tmp/foooooo
                    touch x.pdf y.zip z.mp3 a.pdf
                    GLOBIGNORE=x.pdf:a.pdf
                    ls -1 *


                    Output:




                    y.zip
                    z.mp3





                    share|improve this answer



























                      up vote
                      4
                      down vote













                      Use bash's GLOBIGNORE:



                      GLOBIGNORE=x.pdf:a.pdf
                      rm *
                      unset GLOBIGNORE


                      From bash's man page:




                      GLOBIGNORE:

                      A colon-separated list of patterns defining the set
                      of filenames to be ignored by pathname expansion.




                      A quick test:



                      mkdir /tmp/foooooo
                      cd /tmp/foooooo
                      touch x.pdf y.zip z.mp3 a.pdf
                      GLOBIGNORE=x.pdf:a.pdf
                      ls -1 *


                      Output:




                      y.zip
                      z.mp3





                      share|improve this answer

























                        up vote
                        4
                        down vote










                        up vote
                        4
                        down vote









                        Use bash's GLOBIGNORE:



                        GLOBIGNORE=x.pdf:a.pdf
                        rm *
                        unset GLOBIGNORE


                        From bash's man page:




                        GLOBIGNORE:

                        A colon-separated list of patterns defining the set
                        of filenames to be ignored by pathname expansion.




                        A quick test:



                        mkdir /tmp/foooooo
                        cd /tmp/foooooo
                        touch x.pdf y.zip z.mp3 a.pdf
                        GLOBIGNORE=x.pdf:a.pdf
                        ls -1 *


                        Output:




                        y.zip
                        z.mp3





                        share|improve this answer














                        Use bash's GLOBIGNORE:



                        GLOBIGNORE=x.pdf:a.pdf
                        rm *
                        unset GLOBIGNORE


                        From bash's man page:




                        GLOBIGNORE:

                        A colon-separated list of patterns defining the set
                        of filenames to be ignored by pathname expansion.




                        A quick test:



                        mkdir /tmp/foooooo
                        cd /tmp/foooooo
                        touch x.pdf y.zip z.mp3 a.pdf
                        GLOBIGNORE=x.pdf:a.pdf
                        ls -1 *


                        Output:




                        y.zip
                        z.mp3






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Jun 7 '15 at 12:02

























                        answered Jun 6 '15 at 16:51









                        Cyrus

                        3,0882922




                        3,0882922






















                            up vote
                            3
                            down vote













                            Be careful and compose: use xargs



                            Here's an approach I like, because it lets me be very careful: compose a way to show just the files I want to delete, then send them to rm using xargs. For example:





                            • ls shows me everything


                            • ls | grep pdf shows me the files I want to keep. Hmm.


                            • ls | grep -v pdf shows the opposite: all except what I want to keep. In other words, it shows the list of things I want to delete. I can confirm this before doing anything dangerous.


                            • ls | grep -v pdf | xargs rm sends exactly that list to rm for deletion


                            As I said, I mainly like this for the safety it provides: no accidental rm * for me. Two other advantages:




                            • It's composable; you can use ls or find to get the initial list, as you prefer. You can use anything else you like in the process of narrowing that list - another grep, some awk, or whatever. If you needed to delete only files whose names contain a color, you could build it up this same way.

                            • You can use each tool for its main purpose. I prefer to use find for finding and rm for removal, as opposed to having to remember that find accepts a -delete flag. And if you do this, again, you can compose alternate solutions; maybe instead of rm, you could create a trash command that moves the file to the trash (allowing "undeletion") and pipe to that instead of rm. You don't need to have find support that option, you just pipe to it.


                            Update



                            See comments by @pabouk for how modify this to handle some edge cases, such as line breaks in file names, filenames like my_pdfs.zip, etc.






                            share|improve this answer



















                            • 4




                              I noticed three problems here: a) It will exclude any file containing pdf anywhere in its name. --- b) It will delete PDF files if any of the letter in the suffix are upper case. --- c) It is not a good idea to use output of ls. It will not work with file names containing newlines. Some implementations of ls replace special characters e.g. tab by ?. --- It is better to use: find -maxdepth 1 -print0. (not so short as ls :) ----- To resolve a) and b) use grep -vi '.pdf$' --- complete (but GNU only) solution: find -maxdepth 1 -print0 | grep -viz '.pdf$' | xargs -0 rm
                              – pabouk
                              Dec 1 '14 at 22:12








                            • 1




                              I understand that you meant the solution as an "interactive" process with multiple manual iterations but the checks will be hardly usable for long lists of files and the problems mentioned above could bring easy to overlook mistakes.
                              – pabouk
                              Dec 1 '14 at 22:22






                            • 1




                              @pabouk good points; the real world always complicates things, and your corrections are helpful. :) But I still think this overall approach is best. If there are too many files to visually confirm everything, you can | head -20 to at least see if it looks roughly correct, whereas if you just rm my_pattern, you have no chance to spot a big mistake.
                              – Nathan Long
                              Dec 2 '14 at 14:13






                            • 1




                              You can have find show you the files before you delete them too, leave out the -delete and just use find . -type f ! -name "*.pdf" to print to console, or pipe to less or a file. [and then pipe to xargs to rm if desired like pabouk's comments (with the -print0| ... -0 for weird filenames)]
                              – Xen2050
                              Dec 3 '14 at 7:26















                            up vote
                            3
                            down vote













                            Be careful and compose: use xargs



                            Here's an approach I like, because it lets me be very careful: compose a way to show just the files I want to delete, then send them to rm using xargs. For example:





                            • ls shows me everything


                            • ls | grep pdf shows me the files I want to keep. Hmm.


                            • ls | grep -v pdf shows the opposite: all except what I want to keep. In other words, it shows the list of things I want to delete. I can confirm this before doing anything dangerous.


                            • ls | grep -v pdf | xargs rm sends exactly that list to rm for deletion


                            As I said, I mainly like this for the safety it provides: no accidental rm * for me. Two other advantages:




                            • It's composable; you can use ls or find to get the initial list, as you prefer. You can use anything else you like in the process of narrowing that list - another grep, some awk, or whatever. If you needed to delete only files whose names contain a color, you could build it up this same way.

                            • You can use each tool for its main purpose. I prefer to use find for finding and rm for removal, as opposed to having to remember that find accepts a -delete flag. And if you do this, again, you can compose alternate solutions; maybe instead of rm, you could create a trash command that moves the file to the trash (allowing "undeletion") and pipe to that instead of rm. You don't need to have find support that option, you just pipe to it.


                            Update



                            See comments by @pabouk for how modify this to handle some edge cases, such as line breaks in file names, filenames like my_pdfs.zip, etc.






                            share|improve this answer



















                            • 4




                              I noticed three problems here: a) It will exclude any file containing pdf anywhere in its name. --- b) It will delete PDF files if any of the letter in the suffix are upper case. --- c) It is not a good idea to use output of ls. It will not work with file names containing newlines. Some implementations of ls replace special characters e.g. tab by ?. --- It is better to use: find -maxdepth 1 -print0. (not so short as ls :) ----- To resolve a) and b) use grep -vi '.pdf$' --- complete (but GNU only) solution: find -maxdepth 1 -print0 | grep -viz '.pdf$' | xargs -0 rm
                              – pabouk
                              Dec 1 '14 at 22:12








                            • 1




                              I understand that you meant the solution as an "interactive" process with multiple manual iterations but the checks will be hardly usable for long lists of files and the problems mentioned above could bring easy to overlook mistakes.
                              – pabouk
                              Dec 1 '14 at 22:22






                            • 1




                              @pabouk good points; the real world always complicates things, and your corrections are helpful. :) But I still think this overall approach is best. If there are too many files to visually confirm everything, you can | head -20 to at least see if it looks roughly correct, whereas if you just rm my_pattern, you have no chance to spot a big mistake.
                              – Nathan Long
                              Dec 2 '14 at 14:13






                            • 1




                              You can have find show you the files before you delete them too, leave out the -delete and just use find . -type f ! -name "*.pdf" to print to console, or pipe to less or a file. [and then pipe to xargs to rm if desired like pabouk's comments (with the -print0| ... -0 for weird filenames)]
                              – Xen2050
                              Dec 3 '14 at 7:26













                            up vote
                            3
                            down vote










                            up vote
                            3
                            down vote









                            Be careful and compose: use xargs



                            Here's an approach I like, because it lets me be very careful: compose a way to show just the files I want to delete, then send them to rm using xargs. For example:





                            • ls shows me everything


                            • ls | grep pdf shows me the files I want to keep. Hmm.


                            • ls | grep -v pdf shows the opposite: all except what I want to keep. In other words, it shows the list of things I want to delete. I can confirm this before doing anything dangerous.


                            • ls | grep -v pdf | xargs rm sends exactly that list to rm for deletion


                            As I said, I mainly like this for the safety it provides: no accidental rm * for me. Two other advantages:




                            • It's composable; you can use ls or find to get the initial list, as you prefer. You can use anything else you like in the process of narrowing that list - another grep, some awk, or whatever. If you needed to delete only files whose names contain a color, you could build it up this same way.

                            • You can use each tool for its main purpose. I prefer to use find for finding and rm for removal, as opposed to having to remember that find accepts a -delete flag. And if you do this, again, you can compose alternate solutions; maybe instead of rm, you could create a trash command that moves the file to the trash (allowing "undeletion") and pipe to that instead of rm. You don't need to have find support that option, you just pipe to it.


                            Update



                            See comments by @pabouk for how modify this to handle some edge cases, such as line breaks in file names, filenames like my_pdfs.zip, etc.






                            share|improve this answer














                            Be careful and compose: use xargs



                            Here's an approach I like, because it lets me be very careful: compose a way to show just the files I want to delete, then send them to rm using xargs. For example:





                            • ls shows me everything


                            • ls | grep pdf shows me the files I want to keep. Hmm.


                            • ls | grep -v pdf shows the opposite: all except what I want to keep. In other words, it shows the list of things I want to delete. I can confirm this before doing anything dangerous.


                            • ls | grep -v pdf | xargs rm sends exactly that list to rm for deletion


                            As I said, I mainly like this for the safety it provides: no accidental rm * for me. Two other advantages:




                            • It's composable; you can use ls or find to get the initial list, as you prefer. You can use anything else you like in the process of narrowing that list - another grep, some awk, or whatever. If you needed to delete only files whose names contain a color, you could build it up this same way.

                            • You can use each tool for its main purpose. I prefer to use find for finding and rm for removal, as opposed to having to remember that find accepts a -delete flag. And if you do this, again, you can compose alternate solutions; maybe instead of rm, you could create a trash command that moves the file to the trash (allowing "undeletion") and pipe to that instead of rm. You don't need to have find support that option, you just pipe to it.


                            Update



                            See comments by @pabouk for how modify this to handle some edge cases, such as line breaks in file names, filenames like my_pdfs.zip, etc.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Dec 2 '14 at 14:15

























                            answered Dec 1 '14 at 21:39









                            Nathan Long

                            1408




                            1408








                            • 4




                              I noticed three problems here: a) It will exclude any file containing pdf anywhere in its name. --- b) It will delete PDF files if any of the letter in the suffix are upper case. --- c) It is not a good idea to use output of ls. It will not work with file names containing newlines. Some implementations of ls replace special characters e.g. tab by ?. --- It is better to use: find -maxdepth 1 -print0. (not so short as ls :) ----- To resolve a) and b) use grep -vi '.pdf$' --- complete (but GNU only) solution: find -maxdepth 1 -print0 | grep -viz '.pdf$' | xargs -0 rm
                              – pabouk
                              Dec 1 '14 at 22:12








                            • 1




                              I understand that you meant the solution as an "interactive" process with multiple manual iterations but the checks will be hardly usable for long lists of files and the problems mentioned above could bring easy to overlook mistakes.
                              – pabouk
                              Dec 1 '14 at 22:22






                            • 1




                              @pabouk good points; the real world always complicates things, and your corrections are helpful. :) But I still think this overall approach is best. If there are too many files to visually confirm everything, you can | head -20 to at least see if it looks roughly correct, whereas if you just rm my_pattern, you have no chance to spot a big mistake.
                              – Nathan Long
                              Dec 2 '14 at 14:13






                            • 1




                              You can have find show you the files before you delete them too, leave out the -delete and just use find . -type f ! -name "*.pdf" to print to console, or pipe to less or a file. [and then pipe to xargs to rm if desired like pabouk's comments (with the -print0| ... -0 for weird filenames)]
                              – Xen2050
                              Dec 3 '14 at 7:26














                            • 4




                              I noticed three problems here: a) It will exclude any file containing pdf anywhere in its name. --- b) It will delete PDF files if any of the letter in the suffix are upper case. --- c) It is not a good idea to use output of ls. It will not work with file names containing newlines. Some implementations of ls replace special characters e.g. tab by ?. --- It is better to use: find -maxdepth 1 -print0. (not so short as ls :) ----- To resolve a) and b) use grep -vi '.pdf$' --- complete (but GNU only) solution: find -maxdepth 1 -print0 | grep -viz '.pdf$' | xargs -0 rm
                              – pabouk
                              Dec 1 '14 at 22:12








                            • 1




                              I understand that you meant the solution as an "interactive" process with multiple manual iterations but the checks will be hardly usable for long lists of files and the problems mentioned above could bring easy to overlook mistakes.
                              – pabouk
                              Dec 1 '14 at 22:22






                            • 1




                              @pabouk good points; the real world always complicates things, and your corrections are helpful. :) But I still think this overall approach is best. If there are too many files to visually confirm everything, you can | head -20 to at least see if it looks roughly correct, whereas if you just rm my_pattern, you have no chance to spot a big mistake.
                              – Nathan Long
                              Dec 2 '14 at 14:13






                            • 1




                              You can have find show you the files before you delete them too, leave out the -delete and just use find . -type f ! -name "*.pdf" to print to console, or pipe to less or a file. [and then pipe to xargs to rm if desired like pabouk's comments (with the -print0| ... -0 for weird filenames)]
                              – Xen2050
                              Dec 3 '14 at 7:26








                            4




                            4




                            I noticed three problems here: a) It will exclude any file containing pdf anywhere in its name. --- b) It will delete PDF files if any of the letter in the suffix are upper case. --- c) It is not a good idea to use output of ls. It will not work with file names containing newlines. Some implementations of ls replace special characters e.g. tab by ?. --- It is better to use: find -maxdepth 1 -print0. (not so short as ls :) ----- To resolve a) and b) use grep -vi '.pdf$' --- complete (but GNU only) solution: find -maxdepth 1 -print0 | grep -viz '.pdf$' | xargs -0 rm
                            – pabouk
                            Dec 1 '14 at 22:12






                            I noticed three problems here: a) It will exclude any file containing pdf anywhere in its name. --- b) It will delete PDF files if any of the letter in the suffix are upper case. --- c) It is not a good idea to use output of ls. It will not work with file names containing newlines. Some implementations of ls replace special characters e.g. tab by ?. --- It is better to use: find -maxdepth 1 -print0. (not so short as ls :) ----- To resolve a) and b) use grep -vi '.pdf$' --- complete (but GNU only) solution: find -maxdepth 1 -print0 | grep -viz '.pdf$' | xargs -0 rm
                            – pabouk
                            Dec 1 '14 at 22:12






                            1




                            1




                            I understand that you meant the solution as an "interactive" process with multiple manual iterations but the checks will be hardly usable for long lists of files and the problems mentioned above could bring easy to overlook mistakes.
                            – pabouk
                            Dec 1 '14 at 22:22




                            I understand that you meant the solution as an "interactive" process with multiple manual iterations but the checks will be hardly usable for long lists of files and the problems mentioned above could bring easy to overlook mistakes.
                            – pabouk
                            Dec 1 '14 at 22:22




                            1




                            1




                            @pabouk good points; the real world always complicates things, and your corrections are helpful. :) But I still think this overall approach is best. If there are too many files to visually confirm everything, you can | head -20 to at least see if it looks roughly correct, whereas if you just rm my_pattern, you have no chance to spot a big mistake.
                            – Nathan Long
                            Dec 2 '14 at 14:13




                            @pabouk good points; the real world always complicates things, and your corrections are helpful. :) But I still think this overall approach is best. If there are too many files to visually confirm everything, you can | head -20 to at least see if it looks roughly correct, whereas if you just rm my_pattern, you have no chance to spot a big mistake.
                            – Nathan Long
                            Dec 2 '14 at 14:13




                            1




                            1




                            You can have find show you the files before you delete them too, leave out the -delete and just use find . -type f ! -name "*.pdf" to print to console, or pipe to less or a file. [and then pipe to xargs to rm if desired like pabouk's comments (with the -print0| ... -0 for weird filenames)]
                            – Xen2050
                            Dec 3 '14 at 7:26




                            You can have find show you the files before you delete them too, leave out the -delete and just use find . -type f ! -name "*.pdf" to print to console, or pipe to less or a file. [and then pipe to xargs to rm if desired like pabouk's comments (with the -print0| ... -0 for weird filenames)]
                            – Xen2050
                            Dec 3 '14 at 7:26










                            up vote
                            3
                            down vote













                            I usually solve such problems from the interactive Python interpreter:



                            mic@mic ~ $ python
                            >>> import os
                            >>> for f in os.listdir('.'):
                            ... if not f.endswith('.pdf'):
                            ... os.remove(f)


                            It might be longer than a one-liner with find or xargs, but it's extremely resilient, and I know exactly what it does, without having to research it first.






                            share|improve this answer























                            • For those who get increasingly nervous with every additional line, we could make it into one: for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
                              – Jacob Vlijm
                              Dec 4 '14 at 16:59












                            • python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
                              – mic_e
                              Dec 4 '14 at 17:36












                            • [os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
                              – mic_e
                              Dec 4 '14 at 17:37










                            • nice! the second one gives me a syntax error, don't see why.
                              – Jacob Vlijm
                              Dec 4 '14 at 17:48










                            • strange; it works with both python 3.4 and python 2.7 on my system.
                              – mic_e
                              Dec 4 '14 at 17:56















                            up vote
                            3
                            down vote













                            I usually solve such problems from the interactive Python interpreter:



                            mic@mic ~ $ python
                            >>> import os
                            >>> for f in os.listdir('.'):
                            ... if not f.endswith('.pdf'):
                            ... os.remove(f)


                            It might be longer than a one-liner with find or xargs, but it's extremely resilient, and I know exactly what it does, without having to research it first.






                            share|improve this answer























                            • For those who get increasingly nervous with every additional line, we could make it into one: for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
                              – Jacob Vlijm
                              Dec 4 '14 at 16:59












                            • python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
                              – mic_e
                              Dec 4 '14 at 17:36












                            • [os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
                              – mic_e
                              Dec 4 '14 at 17:37










                            • nice! the second one gives me a syntax error, don't see why.
                              – Jacob Vlijm
                              Dec 4 '14 at 17:48










                            • strange; it works with both python 3.4 and python 2.7 on my system.
                              – mic_e
                              Dec 4 '14 at 17:56













                            up vote
                            3
                            down vote










                            up vote
                            3
                            down vote









                            I usually solve such problems from the interactive Python interpreter:



                            mic@mic ~ $ python
                            >>> import os
                            >>> for f in os.listdir('.'):
                            ... if not f.endswith('.pdf'):
                            ... os.remove(f)


                            It might be longer than a one-liner with find or xargs, but it's extremely resilient, and I know exactly what it does, without having to research it first.






                            share|improve this answer














                            I usually solve such problems from the interactive Python interpreter:



                            mic@mic ~ $ python
                            >>> import os
                            >>> for f in os.listdir('.'):
                            ... if not f.endswith('.pdf'):
                            ... os.remove(f)


                            It might be longer than a one-liner with find or xargs, but it's extremely resilient, and I know exactly what it does, without having to research it first.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Dec 2 '14 at 22:07

























                            answered Dec 2 '14 at 21:58









                            mic_e

                            1314




                            1314












                            • For those who get increasingly nervous with every additional line, we could make it into one: for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
                              – Jacob Vlijm
                              Dec 4 '14 at 16:59












                            • python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
                              – mic_e
                              Dec 4 '14 at 17:36












                            • [os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
                              – mic_e
                              Dec 4 '14 at 17:37










                            • nice! the second one gives me a syntax error, don't see why.
                              – Jacob Vlijm
                              Dec 4 '14 at 17:48










                            • strange; it works with both python 3.4 and python 2.7 on my system.
                              – mic_e
                              Dec 4 '14 at 17:56


















                            • For those who get increasingly nervous with every additional line, we could make it into one: for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
                              – Jacob Vlijm
                              Dec 4 '14 at 16:59












                            • python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
                              – mic_e
                              Dec 4 '14 at 17:36












                            • [os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
                              – mic_e
                              Dec 4 '14 at 17:37










                            • nice! the second one gives me a syntax error, don't see why.
                              – Jacob Vlijm
                              Dec 4 '14 at 17:48










                            • strange; it works with both python 3.4 and python 2.7 on my system.
                              – mic_e
                              Dec 4 '14 at 17:56
















                            For those who get increasingly nervous with every additional line, we could make it into one: for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
                            – Jacob Vlijm
                            Dec 4 '14 at 16:59






                            For those who get increasingly nervous with every additional line, we could make it into one: for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
                            – Jacob Vlijm
                            Dec 4 '14 at 16:59














                            python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
                            – mic_e
                            Dec 4 '14 at 17:36






                            python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
                            – mic_e
                            Dec 4 '14 at 17:36














                            [os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
                            – mic_e
                            Dec 4 '14 at 17:37




                            [os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
                            – mic_e
                            Dec 4 '14 at 17:37












                            nice! the second one gives me a syntax error, don't see why.
                            – Jacob Vlijm
                            Dec 4 '14 at 17:48




                            nice! the second one gives me a syntax error, don't see why.
                            – Jacob Vlijm
                            Dec 4 '14 at 17:48












                            strange; it works with both python 3.4 and python 2.7 on my system.
                            – mic_e
                            Dec 4 '14 at 17:56




                            strange; it works with both python 3.4 and python 2.7 on my system.
                            – mic_e
                            Dec 4 '14 at 17:56










                            up vote
                            2
                            down vote













                            better answer(compared to my previous answer) to this question will be by using the powerful file command.



                            $ file -i abc.pdf
                            abc: application/pdf; charset=binary


                            now your problem:



                            cd <the directory you want to search in>
                            for var in ./*
                            do
                            if file -i "$var" | grep -q 'application/pdf;'
                            then
                            echo "$var"
                            fi
                            done


                            the job of for command is give the files in current directory in the form of variable $var. if-then command outputs the names of pdf files by taking the exit status of 0 from file -i "$var" | grep -q 'application/pdf;' command, it will give exit status of 0 only if it finds pdf files.






                            share|improve this answer



























                              up vote
                              2
                              down vote













                              better answer(compared to my previous answer) to this question will be by using the powerful file command.



                              $ file -i abc.pdf
                              abc: application/pdf; charset=binary


                              now your problem:



                              cd <the directory you want to search in>
                              for var in ./*
                              do
                              if file -i "$var" | grep -q 'application/pdf;'
                              then
                              echo "$var"
                              fi
                              done


                              the job of for command is give the files in current directory in the form of variable $var. if-then command outputs the names of pdf files by taking the exit status of 0 from file -i "$var" | grep -q 'application/pdf;' command, it will give exit status of 0 only if it finds pdf files.






                              share|improve this answer

























                                up vote
                                2
                                down vote










                                up vote
                                2
                                down vote









                                better answer(compared to my previous answer) to this question will be by using the powerful file command.



                                $ file -i abc.pdf
                                abc: application/pdf; charset=binary


                                now your problem:



                                cd <the directory you want to search in>
                                for var in ./*
                                do
                                if file -i "$var" | grep -q 'application/pdf;'
                                then
                                echo "$var"
                                fi
                                done


                                the job of for command is give the files in current directory in the form of variable $var. if-then command outputs the names of pdf files by taking the exit status of 0 from file -i "$var" | grep -q 'application/pdf;' command, it will give exit status of 0 only if it finds pdf files.






                                share|improve this answer














                                better answer(compared to my previous answer) to this question will be by using the powerful file command.



                                $ file -i abc.pdf
                                abc: application/pdf; charset=binary


                                now your problem:



                                cd <the directory you want to search in>
                                for var in ./*
                                do
                                if file -i "$var" | grep -q 'application/pdf;'
                                then
                                echo "$var"
                                fi
                                done


                                the job of for command is give the files in current directory in the form of variable $var. if-then command outputs the names of pdf files by taking the exit status of 0 from file -i "$var" | grep -q 'application/pdf;' command, it will give exit status of 0 only if it finds pdf files.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Jun 5 '15 at 9:31

























                                answered Jun 4 '15 at 16:39









                                Edward Torvalds

                                5,01973978




                                5,01973978






















                                    up vote
                                    1
                                    down vote













                                    rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')


                                    Warning! Better try first



                                    ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')





                                    share|improve this answer



















                                    • 2




                                      Ugh, this is flawed in so many ways: smallo.ruhr.de/award.html#ls, smallo.ruhr.de/award.html#grep, and it totally ignores file names with white space or special characters.
                                      – David Foerster
                                      Dec 3 '14 at 15:47






                                    • 1




                                      You should really use -i with grep for case-insensitive matching.
                                      – muru
                                      Dec 3 '14 at 16:17















                                    up vote
                                    1
                                    down vote













                                    rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')


                                    Warning! Better try first



                                    ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')





                                    share|improve this answer



















                                    • 2




                                      Ugh, this is flawed in so many ways: smallo.ruhr.de/award.html#ls, smallo.ruhr.de/award.html#grep, and it totally ignores file names with white space or special characters.
                                      – David Foerster
                                      Dec 3 '14 at 15:47






                                    • 1




                                      You should really use -i with grep for case-insensitive matching.
                                      – muru
                                      Dec 3 '14 at 16:17













                                    up vote
                                    1
                                    down vote










                                    up vote
                                    1
                                    down vote









                                    rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')


                                    Warning! Better try first



                                    ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')





                                    share|improve this answer














                                    rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')


                                    Warning! Better try first



                                    ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')






                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Dec 3 '14 at 16:17









                                    muru

                                    135k19288488




                                    135k19288488










                                    answered Dec 3 '14 at 15:08









                                    Martín-Blas Pérez Pinilla

                                    1192




                                    1192








                                    • 2




                                      Ugh, this is flawed in so many ways: smallo.ruhr.de/award.html#ls, smallo.ruhr.de/award.html#grep, and it totally ignores file names with white space or special characters.
                                      – David Foerster
                                      Dec 3 '14 at 15:47






                                    • 1




                                      You should really use -i with grep for case-insensitive matching.
                                      – muru
                                      Dec 3 '14 at 16:17














                                    • 2




                                      Ugh, this is flawed in so many ways: smallo.ruhr.de/award.html#ls, smallo.ruhr.de/award.html#grep, and it totally ignores file names with white space or special characters.
                                      – David Foerster
                                      Dec 3 '14 at 15:47






                                    • 1




                                      You should really use -i with grep for case-insensitive matching.
                                      – muru
                                      Dec 3 '14 at 16:17








                                    2




                                    2




                                    Ugh, this is flawed in so many ways: smallo.ruhr.de/award.html#ls, smallo.ruhr.de/award.html#grep, and it totally ignores file names with white space or special characters.
                                    – David Foerster
                                    Dec 3 '14 at 15:47




                                    Ugh, this is flawed in so many ways: smallo.ruhr.de/award.html#ls, smallo.ruhr.de/award.html#grep, and it totally ignores file names with white space or special characters.
                                    – David Foerster
                                    Dec 3 '14 at 15:47




                                    1




                                    1




                                    You should really use -i with grep for case-insensitive matching.
                                    – muru
                                    Dec 3 '14 at 16:17




                                    You should really use -i with grep for case-insensitive matching.
                                    – muru
                                    Dec 3 '14 at 16:17










                                    up vote
                                    1
                                    down vote













                                    rm -i -- !(*@(a|x).pdf)


                                    Read as, remove all files that are not a.pdf or x.pdf.



                                    This works by making use of 2 extended globs, the outer !() to negate the contained glob which itself requires that the glob must match one or more of a or x patterns before the .pdf suffix. See glob#extglob.



                                    $ ls -a
                                    .dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3

                                    $ echo -- !(a.pdf)
                                    -- x.pdf y.zip z.mp3

                                    $ echo -- !(x.pdf)
                                    -- a.pdf y.zip z.mp3

                                    $ echo -- !(a.pdf|x.pdf)
                                    -- y.zip z.mp3

                                    $ echo -- !(@(a|x).pdf) # NOTE.that this matches the .dotfiles* as well
                                    -- . .. .dotfile1 .dotfile2 y.zip z.mp3

                                    $ echo -- !(*@(a|x).pdf) # but this doesn't
                                    -- y.zip z.mp3

                                    $ echo rm -i -- !(*@(a|x).pdf)
                                    rm -i -- y.zip z.mp3





                                    share|improve this answer



























                                      up vote
                                      1
                                      down vote













                                      rm -i -- !(*@(a|x).pdf)


                                      Read as, remove all files that are not a.pdf or x.pdf.



                                      This works by making use of 2 extended globs, the outer !() to negate the contained glob which itself requires that the glob must match one or more of a or x patterns before the .pdf suffix. See glob#extglob.



                                      $ ls -a
                                      .dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3

                                      $ echo -- !(a.pdf)
                                      -- x.pdf y.zip z.mp3

                                      $ echo -- !(x.pdf)
                                      -- a.pdf y.zip z.mp3

                                      $ echo -- !(a.pdf|x.pdf)
                                      -- y.zip z.mp3

                                      $ echo -- !(@(a|x).pdf) # NOTE.that this matches the .dotfiles* as well
                                      -- . .. .dotfile1 .dotfile2 y.zip z.mp3

                                      $ echo -- !(*@(a|x).pdf) # but this doesn't
                                      -- y.zip z.mp3

                                      $ echo rm -i -- !(*@(a|x).pdf)
                                      rm -i -- y.zip z.mp3





                                      share|improve this answer

























                                        up vote
                                        1
                                        down vote










                                        up vote
                                        1
                                        down vote









                                        rm -i -- !(*@(a|x).pdf)


                                        Read as, remove all files that are not a.pdf or x.pdf.



                                        This works by making use of 2 extended globs, the outer !() to negate the contained glob which itself requires that the glob must match one or more of a or x patterns before the .pdf suffix. See glob#extglob.



                                        $ ls -a
                                        .dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3

                                        $ echo -- !(a.pdf)
                                        -- x.pdf y.zip z.mp3

                                        $ echo -- !(x.pdf)
                                        -- a.pdf y.zip z.mp3

                                        $ echo -- !(a.pdf|x.pdf)
                                        -- y.zip z.mp3

                                        $ echo -- !(@(a|x).pdf) # NOTE.that this matches the .dotfiles* as well
                                        -- . .. .dotfile1 .dotfile2 y.zip z.mp3

                                        $ echo -- !(*@(a|x).pdf) # but this doesn't
                                        -- y.zip z.mp3

                                        $ echo rm -i -- !(*@(a|x).pdf)
                                        rm -i -- y.zip z.mp3





                                        share|improve this answer














                                        rm -i -- !(*@(a|x).pdf)


                                        Read as, remove all files that are not a.pdf or x.pdf.



                                        This works by making use of 2 extended globs, the outer !() to negate the contained glob which itself requires that the glob must match one or more of a or x patterns before the .pdf suffix. See glob#extglob.



                                        $ ls -a
                                        .dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3

                                        $ echo -- !(a.pdf)
                                        -- x.pdf y.zip z.mp3

                                        $ echo -- !(x.pdf)
                                        -- a.pdf y.zip z.mp3

                                        $ echo -- !(a.pdf|x.pdf)
                                        -- y.zip z.mp3

                                        $ echo -- !(@(a|x).pdf) # NOTE.that this matches the .dotfiles* as well
                                        -- . .. .dotfile1 .dotfile2 y.zip z.mp3

                                        $ echo -- !(*@(a|x).pdf) # but this doesn't
                                        -- y.zip z.mp3

                                        $ echo rm -i -- !(*@(a|x).pdf)
                                        rm -i -- y.zip z.mp3






                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited May 17 '15 at 11:05

























                                        answered May 17 '15 at 10:48









                                        shalomb

                                        1814




                                        1814






















                                            up vote
                                            1
                                            down vote













                                            portable shell way



                                            $ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'


                                            Pretty much POSIX and compatible with any Bourne-style shell ( ksh, bash, dash ). Well suited for portable scripts and when you can't use bash's extended shell globbing.



                                            perl:



                                            $ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'                                                             


                                            Or slightly cleaner:



                                            $ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'


                                            alternative python



                                            python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'





                                            share|improve this answer



























                                              up vote
                                              1
                                              down vote













                                              portable shell way



                                              $ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'


                                              Pretty much POSIX and compatible with any Bourne-style shell ( ksh, bash, dash ). Well suited for portable scripts and when you can't use bash's extended shell globbing.



                                              perl:



                                              $ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'                                                             


                                              Or slightly cleaner:



                                              $ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'


                                              alternative python



                                              python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'





                                              share|improve this answer

























                                                up vote
                                                1
                                                down vote










                                                up vote
                                                1
                                                down vote









                                                portable shell way



                                                $ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'


                                                Pretty much POSIX and compatible with any Bourne-style shell ( ksh, bash, dash ). Well suited for portable scripts and when you can't use bash's extended shell globbing.



                                                perl:



                                                $ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'                                                             


                                                Or slightly cleaner:



                                                $ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'


                                                alternative python



                                                python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'





                                                share|improve this answer














                                                portable shell way



                                                $ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'


                                                Pretty much POSIX and compatible with any Bourne-style shell ( ksh, bash, dash ). Well suited for portable scripts and when you can't use bash's extended shell globbing.



                                                perl:



                                                $ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'                                                             


                                                Or slightly cleaner:



                                                $ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'


                                                alternative python



                                                python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'






                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Nov 8 '17 at 9:52









                                                muru

                                                135k19288488




                                                135k19288488










                                                answered Nov 8 '17 at 9:16









                                                Sergiy Kolodyazhnyy

                                                68.8k9143303




                                                68.8k9143303






















                                                    up vote
                                                    0
                                                    down vote













                                                    Be Careful of what you're deleting!



                                                    A safe way to test it before trying to delete is to test first with ls, as some uncaught behaviors could delete unwanted files. And you can do it directly outside of the directory. ls is similar to rm, so :



                                                    ls sub/path/to/files/!(*.pdf)


                                                    This will list



                                                    y.zip
                                                    z.mp3


                                                    And now you can see what you're deleting and can safely delete them :



                                                    rm sub/path/to/files/!(*.pdf)


                                                    And that's it. Yo can use wildcard * to be more selective like keeping only programming course documents :



                                                    rm sub/path/to/files/!(*programming*)





                                                    share|improve this answer

























                                                      up vote
                                                      0
                                                      down vote













                                                      Be Careful of what you're deleting!



                                                      A safe way to test it before trying to delete is to test first with ls, as some uncaught behaviors could delete unwanted files. And you can do it directly outside of the directory. ls is similar to rm, so :



                                                      ls sub/path/to/files/!(*.pdf)


                                                      This will list



                                                      y.zip
                                                      z.mp3


                                                      And now you can see what you're deleting and can safely delete them :



                                                      rm sub/path/to/files/!(*.pdf)


                                                      And that's it. Yo can use wildcard * to be more selective like keeping only programming course documents :



                                                      rm sub/path/to/files/!(*programming*)





                                                      share|improve this answer























                                                        up vote
                                                        0
                                                        down vote










                                                        up vote
                                                        0
                                                        down vote









                                                        Be Careful of what you're deleting!



                                                        A safe way to test it before trying to delete is to test first with ls, as some uncaught behaviors could delete unwanted files. And you can do it directly outside of the directory. ls is similar to rm, so :



                                                        ls sub/path/to/files/!(*.pdf)


                                                        This will list



                                                        y.zip
                                                        z.mp3


                                                        And now you can see what you're deleting and can safely delete them :



                                                        rm sub/path/to/files/!(*.pdf)


                                                        And that's it. Yo can use wildcard * to be more selective like keeping only programming course documents :



                                                        rm sub/path/to/files/!(*programming*)





                                                        share|improve this answer












                                                        Be Careful of what you're deleting!



                                                        A safe way to test it before trying to delete is to test first with ls, as some uncaught behaviors could delete unwanted files. And you can do it directly outside of the directory. ls is similar to rm, so :



                                                        ls sub/path/to/files/!(*.pdf)


                                                        This will list



                                                        y.zip
                                                        z.mp3


                                                        And now you can see what you're deleting and can safely delete them :



                                                        rm sub/path/to/files/!(*.pdf)


                                                        And that's it. Yo can use wildcard * to be more selective like keeping only programming course documents :



                                                        rm sub/path/to/files/!(*programming*)






                                                        share|improve this answer












                                                        share|improve this answer



                                                        share|improve this answer










                                                        answered Dec 5 at 17:16









                                                        KeitelDOG

                                                        1




                                                        1






























                                                            draft saved

                                                            draft discarded




















































                                                            Thanks for contributing an answer to Ask Ubuntu!


                                                            • 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.





                                                            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                                            Please pay close attention to the following guidance:


                                                            • 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%2faskubuntu.com%2fquestions%2f555318%2fdelete-all-files-except-files-with-the-extension-pdf-in-a-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

                                                            How did Captain America manage to do this?

                                                            迪纳利

                                                            南乌拉尔铁路局