How can I ignore everything under a folder in Mercurial - version-control

I am looking for an expression for the .hgignore file, to ignore all files beneath a specified folder.
eg: I would like to ignore all files and folders beneath bin
Actually any advice on how the expressions are formed would be great

Alternately:
syntax: glob
bin/**

I did some experiments and I found that the regex syntax on Windows applies to the path starting with the current repository, with backslashes transformed to slashes.
So if your repository is in E:\Dev for example, hg status will apply the patterns against foo/bar/file1.c and such. Anchors apply to this path.
So:
Glob applies to path elements and is rooted to element parts
foo matches any folder (or file) named foo (not to "foobar" nor "barfoo")
*foo* matches any folder or file with "foo" in the name
foo/bar* matches all files in "foo" folder starting with "bar"
Regex is case sensitive, not anchored
Of course, backslash regex special characters like . (dot)
/ matches \ path separator on Windows. \ doesn't match this separator...
foo matches all files and folders with "foo" inside
foo/ matches only folders ending with "foo"
/foo/ matches the folder "foo" somewhere in the path
/foo/bar/ matches the folder "bar" in the folder "foo" somewhere in the path
^foo matches file or folder starting by foo at the root of the repository
foo$ matches file ending with foo
I hope this will help, I found the HGIGNORE(5) page a bit succinct.

Both of those will also filter out a directory called cabin, which might not be what you want. If you're filtering top-level, you can use:
^/bin/
For bin directories below your root, you can omit the ^. There is no need to specify syntax, regexp is the default.

syntax: glob
bin/**
This answer is shown above, however I'd also like to add that * and ** are handled differently. ** is recursive, * is not.
See Hg Patterns

Nevermind, I got it
syntax: regexp
bin\\*
expressions follow standard perl regular expression syntax.

to ignore .class files
syntax: regexp
?\.class

Related

find + cp sparse directory tree

I have a directory tree which, among other files, has files which match certain patterns. For the sake of the discussion, let's assume these are files matching *.foo, or *.bar, or baz*. I want to backup inside my zsh-script only files matching these pattern to a new directory.
The seemingly obvious solution,
find fromdir \( -name '*.{foo,bar}' -o -name 'baz*' \) -exec cp {} todir \;
does not work, because the destination directory for, i.e., fromdir/x/y/a.foo does not exist.
I was thinking of using rsync, but I know only how to exclude certain files from being copied, not how to restrict copying.
I can solve the problem by writing a small auxiliary script, mdcp1file, like this:
#!/bin/zsh
set -u
mkdir -p $2/$1:h # Create destination directory if needed
cp $1 $2
and use it in my find command instead of cp. I wonder whether there is an easier way to solve this problem, either by beefing up the -exec of my find, or by using rsync in a clever way.
As you mention that you make use of zsh, you could just do something like this:
cd /path/to/source/dir
cp --parents **/{*.{foo,bar},baz*}(.) /path/to/destination/dir
Here we make use of:
cp --parents: Bash: Copy named files recursively, preserving folder structure
**: for matching over multiple directories
BRACE EXPANSION: A string of the form foo{xx,yy,zz}bar is expanded to the individual words fooxxbar, fooyybar and foozzbar. Left-to-right order is preserved. This construct may be nested. Commas may be quoted in order to include them literally in a word.
Glob Qualifier (.): Patterns used for filename generation may end in a list of qualifiers enclosed in parentheses. The qualifiers specify which filenames that otherwise match the given pattern will be inserted in the
argument list. The . selects files only.

Using the perl-based rename command to change filenames commencing with dashes

rename is a perl-based command-line tool to rename multiple files.
I have, by accident, created numerous files with names that commence with, or contain, a dash or double dash (- or --). When I try to use rename to get rid of the dashes in, for example, '--the-file-name' using
rename 's/-//g' --the-file-name
rename (understandably) complains that 'the-file-name' is not an allowable option for the rename command.
Is there a way to tell rename that '--the-file-name' is a file name and not an option.
Many commands, including Perl's rename script, support a double-dash to denote the end of a command's options. Hence, to rename --the-file-name to the-file-name:
rename 's/-//g' -- --the-file-name
Perl's Getopt::Long module supports this and is used by rename.
In general, see also: https://unix.stackexchange.com/questions/11376/what-does-double-dash-mean-also-known-as-bare-double-dash
JRFerguson's answer actually works for many commands, not just rename.
Some alternatives also work for commands that do not recognize --:
Prefix the filename with ./ or the full path to it:
rename 's/-//g' ./--*
or
rename 's/-//g' $PWD/--*
Use find (which will also traverse any subdirectories):
find . -name '-*' -exec rename 's/-//g' '{}' ';'
or
find . -name '-*' -exec rename 's/-//g' '{}' +

Load file.q from path containing space character

How to load script file from a path containing spaces?
For example, this works:
\l F:/file.q
Below attempts throw an error:
\l F:/Folder with spaces/file.q
\l "F:/Folder with spaces/file.q"
\l hsym `$"F:/Folder with spaces/file.q"
system "l "F:/Folder with spaces/file.q""
Not exactly practical, but if you need to load files with spaces in the path, you can use windows short file names:
So given a script path: F://Folder with spaces/file with spaces.q
Given
Folder with spaces gets shortname folder~1
script with spaces.q gets shortname filewi~.q
You can load the file as follows in q:
q)system "l F://folder~1/filewi~1.q"
Hello from a q script with spaces in file name
You can get the short name of a file/folder by listing the directory in command print with /x flag (eg. dir /x)
As in general with this situation in windows, you're likely better off avoiding spaces in a filepath.
I know this is a very old post, but just had the same issue. Found a solution that works for me:
system "cd c:/your path/with spaces/"
system "l your_script.q"

Ignore all files and files in subdirectories except one file

Imagine the following structure:
/a/1.txt
/a/2.txt
/a/.keep
/a/b/1.txt
/a/b/2.txt
/a/b/3.txt
/a/b/.keep
/a/b/c/1.txt
/a/b/c/2.txt
/a/b/c/3.txt
/a/b/c/4.txt
/a/b/c/.keep
/d/test.txt
/d/work.txt
I want to ignore all files in a directory except .keep files to obtain the following results:
/a/.keep
/a/b/.keep
/a/b/c/.keep
/d/test.txt
/d/work.txt
My .gitignore file that doesn't work:
/a/*
!.keep
Unfortunatelly, you cannot reinclude files at directories ignored by previous rules, according to the gitignore Documentation:
It is not possible to re-include a file if a parent directory of that file is excluded. Git doesn’t list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined.
So this
/a/*
!/a/**/.keep
will only reinclude /a/.keep but not the others.
You'll have to exclude each file pattern under /a explictly.
/a/**/*.txt
/a/**/.ignore
/a/**/.alsoignore
UPDATE: Or a better solution is to create the following .gitgnore at your /a subdirectory:
*.*
!.keep
(the only drawback is that this solution will also keep files with no extension)
In your case, you should use:
/a/*
!**/.keep
From the gitignore documentation:
A leading "**" followed by a slash means match in all directories. For
example, "**/foo" matches file or directory "foo" anywhere, the same
as pattern "foo". "**/foo/bar" matches file or directory "bar"
anywhere that is directly under directory "foo".

Search for files & file names using silver searcher

Using Silver Searcher, how can I search for:
(non-binary) files with a word or pattern AND
all filenames, with a word or pattern including filenames of binary files.
Other preferences: would like to have case insensitive search and search through dotfiles.
Tried to alias using this without much luck:
alias search="ag -g $1 --smart-case --hidden && ag --smart-case --hidden $1"
According to the man page of ag
-G --file-search-regex PATTERN
Only search files whose names match PATTERN.
You can use the -G option to perform searches on files matching a pattern.
So, to answer your question:
root#apache107:~/rpm-4.12.0.1# ag -G cpio.c size
rpm2cpio.c
21: off_t payload_size;
73: /* Retrieve payload size and compression type. */
76: payload_size = headerGetNumber(h, RPMTAG_LONGARCHIVESIZE);
the above command searches for the word size in all files that matches the pattern cpio.c
Reference:
man page of ag version 0.28.0
Note 1:
If you are looking for a string in certain file types, say all C sources code, there is an undocumented feature in ag to help you quickly restrict searches to certain file types.
The commands below both look for foo in all php files:
find . -name \*.php -exec grep foo {}
ag --php foo
While find + grep looks for all .php files, the --php switch in the ag command actually looks for the following file extensions:
.php .phpt .php3 .php4 .php5 .phtml
You can use --cpp for C++ source files, --hh for .h files, --js for JavaScript etc etc. A full list can be found here
Try this:
find . | ag "/.*SEARCHTERM[^/]*$"
The command find . will list all files.
We pipe the output of that to the command ag "/.*SEARCHTERM[^/]*$", which matches SEARCHTERM if it's in the filename, and not just the full path.
Try adding this to your aliases file. Tested with zsh but should work with bash. The problem you encountered in your example is that bash aliases can't take parameters, so you have to first define a function to use the parameter(s) and then assign your alias to that function.
searchfunction() {
echo $(ag -g $1 --hidden)
echo $(ag --hidden -l $1)
}
alias search=searchfunction
You could modify this example to suit your purpose in a few ways, eg
add/remove the -l flag depending on whether or not you want text results to show the text match or just the filename
add headers to separate text results and filename results
deduplicate results to account for files that match both on filename and text, etc.
[Edit: removed unnecessary --smart-case flag per Pablo Bianchi's comment]
Found this question looking for the same answer myself. It doesn't seem like ag has any native capability to search file and directory names. The answers above from Zach Fogg and Jikku Jose both work, but piping find . can be very slow if you're working in a big directory.
I'd recommend using find directly, which is much faster than piping it through ag:
Linux (GNU version of find)
find -name [pattern]
OSX (BSD version of find)
find [pattern]
If you need more help with find, this guide from Digital Ocean is pretty good. I include this because the man pages for find are outrageously dense if you just want to figure out basic usage.
To add to the previous answers, you can use an "Or" Regular Expression to search within files matching different file extensions.
For example to just search a string in C++ header files [.hpp] and Makefiles [.mk] ) :
ag -G '.*\.(hpp|mk)' my_string_to_search
After being unsatisfied with mdfind, find, locate, and other attempts, the following worked for me. It uses tree to get the initial list of files, ag to filter out directories, and then awk to print the matching files themselves.
I wound up using tree because it was more (and more easily) configurable than the other solutions I tried and is fast.
This is a fish function:
function ff --description 'Find files matching given string'
tree . --prune --matchdirs -P "*$argv*" -I "webpack" -i -f --ignore-case -p |
ag '\[[^d].*' |
awk '{print $2}'
end
This gives output similar to the following:
~/temp/hello_world $ ff controller
./app/controllers/application_controller.rb
./config/initializers/application_controller_renderer.rb
~/temp/hello_world $