Delete all files except files with the extension pdf in a directory
up vote
48
down vote
favorite
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
add a comment |
up vote
48
down vote
favorite
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
add a comment |
up vote
48
down vote
favorite
up vote
48
down vote
favorite
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
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
command-line bash
edited May 18 '15 at 9:36
lesmana
11.6k84048
11.6k84048
asked Dec 1 '14 at 11:47
Starkers
1,15982137
1,15982137
add a comment |
add a comment |
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
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
|
show 2 more comments
up vote
41
down vote
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
Better approach IMO.
– Takkat
Dec 1 '14 at 12:21
What about files without an extension? FWIW, in zsh it’srm *~*.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
|
show 2 more comments
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
6
This approach is much safer than directly usingrm
.
– Seth♦
Dec 2 '14 at 20:13
add a comment |
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!
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
add a comment |
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
add a comment |
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 torm
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
orfind
to get the initial list, as you prefer. You can use anything else you like in the process of narrowing that list - anothergrep
, someawk
, 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 andrm
for removal, as opposed to having to remember thatfind
accepts a-delete
flag. And if you do this, again, you can compose alternate solutions; maybe instead ofrm
, you could create atrash
command that moves the file to the trash (allowing "undeletion") and pipe to that instead ofrm
. You don't need to havefind
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.
4
I noticed three problems here: a) It will exclude any file containingpdf
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 ofls
. It will not work with file names containing newlines. Some implementations ofls
replace special characters e.g. tab by?
. --- It is better to use:find -maxdepth 1 -print0
. (not so short asls
:) ----- To resolve a) and b) usegrep -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 justrm 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 usefind . -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
add a comment |
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.
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
|
show 4 more comments
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.
add a comment |
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}')
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
withgrep
for case-insensitive matching.
– muru
Dec 3 '14 at 16:17
add a comment |
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
add a comment |
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(".")))'
add a comment |
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*)
add a comment |
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
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
|
show 2 more comments
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
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
|
show 2 more comments
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
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
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
|
show 2 more comments
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
|
show 2 more comments
up vote
41
down vote
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
Better approach IMO.
– Takkat
Dec 1 '14 at 12:21
What about files without an extension? FWIW, in zsh it’srm *~*.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
|
show 2 more comments
up vote
41
down vote
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
Better approach IMO.
– Takkat
Dec 1 '14 at 12:21
What about files without an extension? FWIW, in zsh it’srm *~*.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
|
show 2 more comments
up vote
41
down vote
up vote
41
down vote
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
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
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’srm *~*.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
|
show 2 more comments
Better approach IMO.
– Takkat
Dec 1 '14 at 12:21
What about files without an extension? FWIW, in zsh it’srm *~*.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
|
show 2 more comments
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
6
This approach is much safer than directly usingrm
.
– Seth♦
Dec 2 '14 at 20:13
add a comment |
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
6
This approach is much safer than directly usingrm
.
– Seth♦
Dec 2 '14 at 20:13
add a comment |
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
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
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 usingrm
.
– Seth♦
Dec 2 '14 at 20:13
add a comment |
6
This approach is much safer than directly usingrm
.
– 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
add a comment |
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!
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
add a comment |
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!
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
add a comment |
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!
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!
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
add a comment |
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
add a comment |
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
add a comment |
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
add a comment |
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
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
edited Jun 7 '15 at 12:02
answered Jun 6 '15 at 16:51
Cyrus
3,0882922
3,0882922
add a comment |
add a comment |
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 torm
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
orfind
to get the initial list, as you prefer. You can use anything else you like in the process of narrowing that list - anothergrep
, someawk
, 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 andrm
for removal, as opposed to having to remember thatfind
accepts a-delete
flag. And if you do this, again, you can compose alternate solutions; maybe instead ofrm
, you could create atrash
command that moves the file to the trash (allowing "undeletion") and pipe to that instead ofrm
. You don't need to havefind
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.
4
I noticed three problems here: a) It will exclude any file containingpdf
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 ofls
. It will not work with file names containing newlines. Some implementations ofls
replace special characters e.g. tab by?
. --- It is better to use:find -maxdepth 1 -print0
. (not so short asls
:) ----- To resolve a) and b) usegrep -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 justrm 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 usefind . -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
add a comment |
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 torm
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
orfind
to get the initial list, as you prefer. You can use anything else you like in the process of narrowing that list - anothergrep
, someawk
, 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 andrm
for removal, as opposed to having to remember thatfind
accepts a-delete
flag. And if you do this, again, you can compose alternate solutions; maybe instead ofrm
, you could create atrash
command that moves the file to the trash (allowing "undeletion") and pipe to that instead ofrm
. You don't need to havefind
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.
4
I noticed three problems here: a) It will exclude any file containingpdf
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 ofls
. It will not work with file names containing newlines. Some implementations ofls
replace special characters e.g. tab by?
. --- It is better to use:find -maxdepth 1 -print0
. (not so short asls
:) ----- To resolve a) and b) usegrep -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 justrm 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 usefind . -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
add a comment |
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 torm
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
orfind
to get the initial list, as you prefer. You can use anything else you like in the process of narrowing that list - anothergrep
, someawk
, 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 andrm
for removal, as opposed to having to remember thatfind
accepts a-delete
flag. And if you do this, again, you can compose alternate solutions; maybe instead ofrm
, you could create atrash
command that moves the file to the trash (allowing "undeletion") and pipe to that instead ofrm
. You don't need to havefind
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.
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 torm
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
orfind
to get the initial list, as you prefer. You can use anything else you like in the process of narrowing that list - anothergrep
, someawk
, 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 andrm
for removal, as opposed to having to remember thatfind
accepts a-delete
flag. And if you do this, again, you can compose alternate solutions; maybe instead ofrm
, you could create atrash
command that moves the file to the trash (allowing "undeletion") and pipe to that instead ofrm
. You don't need to havefind
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.
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 containingpdf
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 ofls
. It will not work with file names containing newlines. Some implementations ofls
replace special characters e.g. tab by?
. --- It is better to use:find -maxdepth 1 -print0
. (not so short asls
:) ----- To resolve a) and b) usegrep -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 justrm 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 usefind . -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
add a comment |
4
I noticed three problems here: a) It will exclude any file containingpdf
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 ofls
. It will not work with file names containing newlines. Some implementations ofls
replace special characters e.g. tab by?
. --- It is better to use:find -maxdepth 1 -print0
. (not so short asls
:) ----- To resolve a) and b) usegrep -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 justrm 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 usefind . -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
add a comment |
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.
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
|
show 4 more comments
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.
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
|
show 4 more comments
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.
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.
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
|
show 4 more comments
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
|
show 4 more comments
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.
add a comment |
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.
add a comment |
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.
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.
edited Jun 5 '15 at 9:31
answered Jun 4 '15 at 16:39
Edward Torvalds
5,01973978
5,01973978
add a comment |
add a comment |
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}')
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
withgrep
for case-insensitive matching.
– muru
Dec 3 '14 at 16:17
add a comment |
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}')
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
withgrep
for case-insensitive matching.
– muru
Dec 3 '14 at 16:17
add a comment |
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}')
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}')
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
withgrep
for case-insensitive matching.
– muru
Dec 3 '14 at 16:17
add a comment |
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
withgrep
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
add a comment |
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
add a comment |
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
add a comment |
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
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
edited May 17 '15 at 11:05
answered May 17 '15 at 10:48
shalomb
1814
1814
add a comment |
add a comment |
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(".")))'
add a comment |
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(".")))'
add a comment |
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(".")))'
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(".")))'
edited Nov 8 '17 at 9:52
muru
135k19288488
135k19288488
answered Nov 8 '17 at 9:16
Sergiy Kolodyazhnyy
68.8k9143303
68.8k9143303
add a comment |
add a comment |
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*)
add a comment |
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*)
add a comment |
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*)
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*)
answered Dec 5 at 17:16
KeitelDOG
1
1
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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