ive been setting up Grunt for my web app to auto build it and im seeing paths like
/path/to/file/**/*.js
i understand what one wildcard means, but what does 2 in a row mean?
/path/to/file/**/*.js matches any number of directories between /path/to/file/ and /*.js. As opposed to /path/to/file/*/*.js, which matches a single directory between /path/to/file/ and /*.js.
this matchers called "glob pattern" they are widely used in shell script and in CLI tools like grunt or npm .they '**' means -- "Matches zero or more directories, but will never match the directories . and .. "
you can read more in the docs
glob pattern
Related
I'm relatively new to bash and I have tried multiples solutions that I could find here but none of them seem to be working in my case. It's pretty simple, I have a folder that looks like this:
- images/
- 0_image_1.jpg
- 0_image_2.jpg
- 0_image_3.jpg
- 1_image_1.jpg
- 1_image_2.jpg
- 1_image_3.jpg
and I would like to move these jpg files into subfolders based on the prefix number like so:
- images_0/
- 0_image_1.jpg
- 0_image_2.jpg
- 0_image_3.jpg
- images_1/
- 1_image_1.jpg
- 1_image_2.jpg
- 1_image_3.jpg
Is there a bash command that could do that in a simple way ?
Thank you
for src in *_*.jpg; do
dest=images_${src%%_*}/
echo mkdir -p "$dest"
echo mv -- "$src" "$dest"
done
Remove both echos if the output looks good.
I would do this with rename a.k.a. Perl rename. It is extremely powerful and performant. Here's a command for your use case:
rename --dry-run -p '$_="images_" . substr($_,0,1) . "/" . $_' ?_*jpg
Let's dissect that. At the right end, we specify we only want to work on files that start with a single character/digit before an underscore so we don't do damage trying to apply the command to files it wasn't meant for. Then --dry-run means it doesn't actually do anything, it just shows you what it would do - this is a very useful feature. Then -p which handily means "create any necessary directories for me as you go". Then the meat of the command. It passes you the current filename in a variable called $_ and we then need to create a new variable called $_ to say what we want the file to be called. In this case we just want the word images_ followed by the first digit of the existing filename and then a slash and the original name. Simples!
Sample Output
'0_image_1.jpg' would be renamed to 'images_0/0_image_1.jpg'
'0_image_2.jpg' would be renamed to 'images_0/0_image_2.jpg'
'1_image_3.jpg' would be renamed to 'images_1/1_image_3.jpg'
Remove the --dry-run and run again for real, if the output looks good.
Using rename has several benefits:
that it will warn and avoid any conflicts if two files rename to the same thing,
that it can rename across directories, creating any necessary intermediate directories on the way,
that you can do a dry run first to test it,
that you can use arbitrarily complex Perl code to specify the new name.
Note: On macOS, you can install rename using homebrew:
brew install rename
Note: On some Ones, rename is referred to as prename for Perl rename.
I am trying to configure collectCoverageFrom for jest to look up all my .ts files expect those with .module.ts but I can not find the correct glob pattern.
As peer what I understand this should work :
src/**/**.!(.module.ts).ts
but for some reason it does not takes files like this one:
src/pages/home/home.ts
What I am doing wrong?
Try this
src/**/!(*module)*.ts
You can test this glob pattern using globster https://globster.xyz/?q=**%2F!(module).ts
The solution was to use two rules ['src/**/*.ts','!**/*.module.ts']].
Looks like the second rule filters the first rule results: "Take all the *.ts files except(!) *.module.ts"
I know how regex and wildcards work in general, but I don't really understand why you can use them as parameters.
ls /[!\(][!\(][!\(]/
command results in the following output
...
com.apple.launchd.AIPZ6SAfpO
com.apple.launchd.HarlOx3LWS
com.apple.launchd.VmTi5KDz1h
powerlog
/usr/:
X11 include libexec sbin standalone
bin lib local share
/var/:
agentx empty log netboot rwho
at folders ma networkd spool
audit install mail root tmp
backups jabberd msgs rpc vm
db lib mysql run yp
from my understanding this should match every three character folder name not containing slash /[!\(][!\(][!\(]/
But why can I use it as parameter?
You can't use regular expressions as parameters (or rather, the shell will not treat a string as a regular expression when placed in a parameter). The unquoted glob /[!\(][!\(][!\(]/ matches, in order:
A slash.
Three characters which are not starting brackets.
A slash.
In other words, three-letter root directories not containing ( anywhere.
The shell expands globs to zero (in case of Bash's nullglob, for example) or more arguments which may be passed to execve, as in this command:
$ strace -fe execve echo *
execve("/usr/bin/echo", ["echo", "directory1", "directory2"], 0x7ffcff705ce8 /* 44 vars */) = 0
Not, you don't know.... shell patterns are described in glob(3) while regular expressions (a more elaborate concept) are described in regex(3) Two different libraries used for similar purposes. sh(1) doesn't use regular expressions when substituting parameters at all. It only uses the glob(3) library.
Because that's how the shell works. Any arguments containing (unquoted) glob characters/expressions, are expanded to filenames. That's what happens in, say rm *.txt (since * is a glob character), and that's what happens in ls /[!\(][!\(][!\(]/ (since [abc] is a glob expression).
They're not regular expressions, though. See e.g. https://mywiki.wooledge.org/glob for the syntax.
In my directory there are the files:
file1.txt fix.log fixRRRRRR.log fixXXXX.log output.txt
In order to understand the find command, I tried a lot of stuff among other things I wanted to use 2 wildcards. Target was to find files that start with an f and have an extension starting with an l.
$ find . f*.l*
./file1.txt
./fix.log
./fixRRRRRR.log
./output.txt
./fixXXXX.log
fix.log
fixRRRRRR.log
fixXXXX.log
I read in a forum answer to use quotation marks with find find . "f*.l*" with the result: `
./file1.txt
./fix.log
./fixRRRRRR.log
./output.txt
./fixXXXX.log
It results in find: ‘f*.l*’: No such file or directory
What am I doing wrong, where is my error in reasoning?
Thanks for an answer.
find doesn't work like that. In general find's call form looks like:
find [entry1] [entry2] ... [expressions ...]
Where an entry is a starting point where find starts the search for files.
In your case, you haven't actually supplied any expressions.
In the first command (without quotes), the shell expands the wildcards to a list of matching files (in the current directory), then passes the list to find as arguments. So find . f*.l* is essentially equivalent to find . fix.log fixRRRRRR.log fixXXXX.log. As a result, find treats all of those arguments as directories/files to search (not patterns to search for), and lists all files under ., (everything) then all files under fix.log (it's not a directory, so that's just the file itself), then all files under fixRRRRRR.log and finally all files under fixXXXX.log.
In the second one (with quotes) it searches for all files beneath the current directory (.) and tries the same for the file literally called "f*.l*".
Actually you are likely seeking for the "-name" expression, which may be used like this:
find . -name "f*.l*"
I am writing my Karma conf based on
http://karma-runner.github.io/1.0/config/preprocessors.html
The key for the preprocessor is a glob string.
This works for all folders within the build folder:
build/**/!(*.spec|*.bundle|*.min).js
However, I don't want all folders. I wanted folder 1,2,4,5 NOT folder 3
Can I write that in a single string (as seems to be required by karma)?
Something like
build/(folder1|folder2|folder4|folder5)/!(*.spec|*.bundle|*.min).js
or even better
build/** but not folder 3/!(*.spec|*.bundle|*.min).js
This covers it
https://github.com/karma-runner/karma-coverage/issues/13
Quoting it
You can make this work using brace expansion. For #chevalric's case, the following pattern will do it:
src/*/{*.js,!(test)/**/*.js}
This expands to two patterns:
src/*/*.js # Match files in the module root
src/*/!(test)/**/*.js # Match files in all subfolders except test/
Also it later says ..
src/*/!(test)/**/*.js
worked
However, for me, I could not test that this worked for various reasons.