Hot answers tagged wildcards
59
The a* and *a* syntax is implemented by the shell, not by the ls command.
When you type
ls a*
at your shell prompt, the shell expands a* to a list of all files in the current directory whose names start with a. For example, it might expand a* to the sequence a1 a2 a3, and pass those as arguments to ls. The ls command itself never sees the * character; it ...
40
You need to quote your argument error* because the shell expands it. So what you're actually running now is find -name error_log, because that's what the shell can expand it to (there's a file named error_log in your current directory).
find . -name 'error*'
Is the correct invocation for your use case.
29
Globs are not regular expressions. In general, the shell will try to interpret anything you type on the command line that you don't quote as a glob. Shells are not required to support regular expressions at all (although in reality many of the fancier more modern ones do, e.g. the =~ regex match operator in the bash [[ construct).
The .??* is a glob. ...
27
Rsync's filter rules can seem daunting when you read the manual, but there are a few simple principles that suffice in many cases:
Inclusions and exclusions:
Excluding files by name or by location is easy: --exclude=*~, --exclude=/some/relative/location.
If you only want to match a few files or locations, include them, include every directory leading to ...
26
A shell assignment is a single word, with no space after the equal sign. So what you wrote assigns an empty value to thefile; furthermore, since the assignment is grouped with a command, it makes thefile an environment variable and the assignment is local to that particular command, i.e. only the call to ls sees the assigned value.
You want to capture the ...
25
The command ls defaults to ls .: List all entries in the current directory.
The command ls * means 'run ls on the expansion of the * shell pattern'
The * pattern is processed by the shell, and expands to all entries in the current directory, except those that start with a .. It will go one level deep.
The interpretation of double or triple * patterns ...
21
You can use the mogrify command for this. Normally, it modifies files in-place, but when converting formats, it writes a new file (just changing the extension to match the new format). Thus:
mogrify -format pdf -- *.jpg
(Like enzotib's ./*.jpg, the -- prevents any strange filenames from being interpreted as switches. Most commands recognize -- to mean ...
20
See Keith Thompson’s answer; but to explain why ls --directory a* shows files and directories: The --directory option does not suppress non-directory files. Instead, it lists the directories as such, while it would otherwise list their content. Example:
$ mkdir foo
$ touch foo/bar
$ ls foo
bar
$ ls --directory foo
foo
19
Zsh
mv Foo/*(DN) Bar/
or
setopt -s glob_dots
mv Foo/*(N) Bar/
(Leave out the (N) if you know the directory is not empty.)
Bash
shopt -s dotglob nullglob
mv Foo/* Bar/
Ksh93
If you know the directory is not empty:
FIGNORE='.?(.)'
mv Foo/* Bar/
Standard (POSIX) sh
for x in Foo/* Foo/.[!.]* Foo/..?*; do
if [ -e "$x" ]; then mv -- "$x" Bar/
done
...
19
Those are not regular expressions, they are examples of Bash's parameter expansion: the substitution of a variable or a special parameter by its value. The Wooledge Wiki has a good explanation.
Basically, in the example you have, ${0##*/} translates as:
for the variable $0, and the pattern '/', the two hashes mean from the beginning of the parameter, ...
15
It isn't deleting them because it recognises the filenames as arguments (unquoted, in this situation * expands to -f -i ize). To delete these files, either do rm -- *, or rm ./*. -- signifies the end of arguments, ./ uses the link to the current directory to circumvent rm's argument detection.
Generally ./* is preferable, as some programs do not accept -- ...
15
This is actually done by your shell, not by ls.
In bash, you'd use:
shopt -s nocaseglob
and then run your command.
Or in zsh:
unsetopt CASE_GLOB
and then your command.
You might want to put that into .bashrc or .zshrc, respectively.
Alternatively, with zsh:
setopt extendedglob
ls -d -- (#i)*abc*
(that is turn case insensitive globbing on on a ...
14
grep -r foo * doesn't look for matches in hidden files or directories,
also * is expanded by the shell so you might end up with an Argument list too long error when there are a lot of entries in the current directory, or some other errors or misbehaviour if the name of some of the files or directories starts with a dash character.
Invocation grep -r foo . ...
14
With globs :
for dir in */; do mkdir -- "$dir/tmp1"; done
NOTE
I treat only dirs (including symlinks to dirs) with the little hack of using */ as a glob
If you want to create multiple subdirs at once :
for dir in */; do mkdir -- "$dir"/{tmp1,foo,bar,qux}; done
13
Use */ to match only directories.
chmod g+s /var/www/*/
To match all directories and subdirectories use **/*/ (provided you have globstar enabled in bash):
shopt -s globstar
chmod g+s /var/www/**/*/
11
Under ksh, bash or zsh:
svn mv !(2010) 2010
Under bash, you need to run shopt -s extglob first (put it in your ~/.bashrc). Under zsh, you need to run setopt -o ksh_glob first (put it in your ~/.zshrc).
This doesn't move dot files (files whose name begins with .). If you have some, move them separately. Take care to exclude the .svn directory if you have ...
11
Rsync handles this nicely.
Example copy all: rsync -aP /folder1/* /folder/2
Example copy all with exclusion: rsync -aP --exclude=x /folder1/* /folder2/
The -aP switch:
a: Similar to cp -a, recursive, etc.
P: Shows progress, a nice feature of rsync.
11
You can use the -delete flag of find (first test with -ls)
find -not -name "*.c" -delete
If you do not want to use find, but only files in the current directory, you could do
rm !(*.c)
Make sure in bash that with shopt -s extglob the correct globbing is set.
10
x?? is expanded at the time of function call. So your function is already called with xaa xab xac... .
The simplest way would be to change the ordering of your parameters:
makeaudiobook () {
count=1
almbumartist=$1
shift
for f in "$@"; do
preprocess "$f" > "$f"-preprocessed
text2wave "$f"-preprocessed -o "$f".wav
lame -b 16 --tt ...
9
Use the find command.
Find all files (recursively) matching a regex: find . -type f -regex '/ex/'
Find all files (recursively) matching a regex and delete them: find . -type f -regex '/ex/' -exec rm {} \;
The brackets store the found pathname, and the backslash escapes the semicolon because it's passed to find; without escaping it, it would be consumed ...
9
In bash or ksh, put the file names in an array, and iterate over that array in reverse order.
files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
bar "${files[$i]}"
done
The code above also works in zsh if the ksh_arrays option is set (it is in ksh emulation mode). There's a simpler method in zsh, which is to reverse the order of the ...
9
By default, shells expand wildcards if a file matches them but keep unexpanded without match. For example, if you run touch /tmp/111; touch /tmp/11* this will create and then update mtime on /tmp/111, but if /tmp is empty but you call touch /tmp/11* you will get file named "11*" in /tmp.
This is rather weird feature of shells. Sometimes proper expanding ...
9
My best guess is that on your client machine, from which you ran ssh, that you also have a directory named /var/lib/edumate/backup/weekly. At the time you ran it, that directory on your client machine contained only the one file. But now it contains all the files you expect.
What happens is that the wildcard matching happens on the client machine rather ...
9
There is no option in ls to filter on filename but in most of the shells there are globbing extension man bash /Pattern Matching
ksh
ls -lrtd -- *@(day|night)*
zsh
setopt extendedglob
ls -lrtd -- *(day|night)*
or:
setopt kshglob
ls -lrtd -- *@(day|night)*
bash
shopt -s extglob
ls -lrtd -- *@(day|night)*
In any of these three shells you can do ...
9
You can just use *; there is no need for *.*. File extensions are not special on Unix. * matches zero or more characters—including a dot. So it matches foo.png, because that's zero or more characters (seven, to be exact).
Note that * by default doesn't match files beginning with a dot (neither does *.*). This is often what you want. If not, in bash, if you ...
9
You can't combine them with bash (or POSIXly), you have to do it in two steps.
i=${x#*/}; i=${i%%/*}
That's portable to any POSIX shell. If you need portability to the Bourne shell (but why would you tag your question /bash then?) as well in case you're porting to Solaris and are forced to use /bin/sh instead of the standard sh there, or porting to 20 ...
9
You have an alias (or function) for ls that colorizes the output. What does type -a ls give you? Instead use
vim $(command ls ...)
However: don't parse ls
Try
shopt -s nullglob globstar
printf "%s\n" **/*.{h,cpp}
8
First of all, the shell is globbing the '*' for you. Either escape it with \ or use quotes around *.html
Like so:
find myDir -name "*.html" or find myDir -name \*.html
Skip the use of xargs with find's -exec switch:
find myDir -name "*.html" -exec cp {} ~/otherDir \;
This works because {} takes the place of the file that find found, and is executed once ...
8
From man bash:
${parameter#word}
${parameter##word}
Remove matching prefix pattern. The word is expanded to produce a pattern
just as in pathname expansion. If the pattern matches the beginning of the
value of parameter, then the result of the expansion is the expanded value of
parameter with the shortest matching pattern (the # ...
8
$ sudo mv /var/lib/mysql/db_test/* /var/lib/mysql/backup
When you type that, you user's shell tries do expand the file list for /var/lib/mysql/db_test/*. If your user doesn't have access to that directory, that will fail, and no substitution is done.
So the mv command run by sudo will get /var/lib/mysql/db_test/* as a literal filename. A file with such a ...
Only top voted, non community-wiki answers of a minimum length are eligible


