I am learning the shell commands and came across the short tags eg.[0-9],[[:digit:]] etc.. As a proof of concept i tried deleting all the files with the rm command(i know its not a good practise but i am trying to understand how things work),like this
rm [0-9].txt
there were two files in the directory 0.txt and 9.txt and it deleted the files 0.txt and 9.txt .I guessed that the expression [0-9] is expanded and then read as 0.txt 1.txt 2.txt …. However when you try only
rm 5.txt,and the file does not exist, an error is thrown..
someone please tell me how the shorthand commands work when used with rm or ls.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
This is called globbing (link to bash documentation, but this is not specific to bash).
When you ran rm [0-9].txt, the shell expanded [0-9].txt to the list of files present in the directory that matched that pattern. Then that list is passed as an argument to rm (each file as a separate argument).
So no, the shell didn’t expand it to 0.txt 1.txt ... 9.txt, it looks at the files that matched.
Why you run just rm 5.txt, there is no glob pattern to expand, so the argument is passed as-is to rm, which notices that the file doesn’t exist and complains.
Try something else: same command rm [0-9].txt, but in a directory that doesn’t have any file that matches the pattern. You’ll notice rm complains again, but this time it will say:
rm: cannot remove '[0-9].txt': No such file or directory
This is what happens (by default anyway) if a glob pattern doesn’t match anything: the shell doesn’t expand it and leaves it untouched.
POSIX reference for this sort of pattern matching: Pattern Matching Notation.
Method 2
Don’t test with rm, test with echo!
[0-9].txt is a wildcard pattern (also called a glob). It expands to a list of existing file names. In a glob pattern, you can use three kinds of wildcards:
- The character
*matches any sequence of characters (including the empty sequence). - The character
?matches any one character. - The bracket expression
[…]matches any one character that appears within the brackets.
[0-9]is a shortcut for[0123456789]. You can use a-between two characters inside brackets to mean those two characters and any two characters in between. For example,[0-9a-z_]matches a digit or a lowercase letter or an underscore.
There are a few more rules regarding brackets that I won’t mention here.
To reiterate, all those constructs only match existing files. [0-9].txt won’t expand to 5.txt if there is no file with that name, any more than *.txt would expand to dfiojedfoi.txt if there is no file with that name.
Example:
$ ls 0.txt 10.txt 1a.txt 9.txt hello.txt world.txt $ echo [0-9].txt 0.txt 9.txt $ echo [0-9][0-9].txt 10.txt $ echo [0-9][0-9][0-9].txt [0-9][0-9][0-9].txt $ echo [0-9]?.txt 1a.txt 10.txt $ echo [10-19].txt 0.txt 9.txt $ echo *.txt 0.txt 1a.txt 9.txt 10.txt hello.txt world.txt $ echo *l* hello.txt world.txt
echo [0-9][0-9][0-9].txt just repeats the pattern because there is no matching file.
Make sure you understand why [10-19].txt matched just those two files and not 10.txt or 19.txt.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0