Gnuwin32 find.exe expands wildcard before performing search [closed] - find

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 2 years ago.
Improve this question
I am using Gnuwin32 binaries on a Windows environment.
When I want to find files of a certain type, let's say PDF, I usually run:
find . -iname '*.pdf' -print
This works perfectly on any UNIX system.
find.exe . -iname "*.pdf" -print
But under Windows, having replaced single quotes with double-quotes, it only works when there is no pdf file in the current directory, otherwise the * gets expanded.
Worse: when there is exactly one PDF file in the current directory, it will expand, there will be no syntax error and you will get wrong results.
I have tried escaping the * with a caret, a backslash, a star itself, putting inside double quotes: nothing works for me.
Real example:
Okay, here are all my files:
C:\tmp>find . -type f
./a/1.pdf
./a/2.pdf
./a/aa/1.pdf
./b/1.pdf
./b/bb/1.pdf
./b/bb/2.pdf
Good behaviour, wildcard was not expanded
C:\tmp>find . -iname "*.pdf"
./a/1.pdf
./a/2.pdf
./a/aa/1.pdf
./b/1.pdf
./b/bb/1.pdf
./b/bb/2.pdf
C:\tmp>cd a
Caution, inconsistent behaviour, wildcard was expanded:
C:\tmp\a>find . -iname "*.pdf"
find: paths must precede expression
Usage: find [-H] [-L] [-P] [path...] [expression]
C:tmp\a>cd ..\b
Caution, inconsistent behaviour, wildcard was expanded :
C:\tmp\b>find . -iname "*.pdf"
./1.pdf
./bb/1.pdf
Thank you

I have found myself the solution to my problem.
Gnuwin32's find.exe is not working on recent Windows Versions (Vista, Seven) because it expands wildcards matching only the contents of the current directory.
Similarly, an old version of find.exe from UnxUtils suffered the same bug.
The latest find.exe from UnxUtils is working.

One workaround is to add a wildcard/expansion that the Windows shell does not expand, but GNU find does:
find.exe . -name *[.:]pdf -print
The Windows shell[*] does not interpret/expand square braces. In addition, colon is not a valid character in Windows filenames, so this pattern cannot match any Windows filename, and the Windows shell will always pass the pattern through to find.exe.
Find.exe will then find any files ending in .pdf or :pdf , but since no files can have a name ending in :pdf under Windows, it will only find files ending in .pdf.
[*] It's actually the C runtime that does/not perform these wildcard expansions. I don't understand the Win32 C runtime well enough to refine the distinction, so for now for the purpose of this workaround, I'm just saying 'shell'.

I suffered this problem this afternoon.
Benoit's UnxUtils can work.
I also find MinGW's find.exe can work,it is under my
"MinGW\msys\1.0\bin"
directory. And it is consistent with the manual.
gnuwin32 and UnxUtils: find.exe . -name GameCli* work, but
find.exe . -name 'GameCli*' doesn't work.
MinGW's find.exe . -name 'GameCli*' work.

I haven't found anything better than just avoiding wildcard characters
find.exe . -iregex ".+\.pdf" -print

#OP, i have consistent behaviour
C:\test\temp>find . -iname "*.txt"
./1.txt
./2.txt
C:\test\temp>cd a
C:\test\temp\a>find . -iname "*.txt"
C:\test\temp\a>cd ..\b
C:\test\temp\b>find . -iname "*.txt"
C:\test\temp\b>find --version
GNU find version 4.2.20
Features enabled: CACHE_IDS D_TYPE
You may want to try to use findutils instead of UnxUtils.

Related

xdg-open multiple files without extension

I want to open multiple files with xdg-open with the following codes
me#host:~/Downloads$ find . -type f -iregex "./[^.]*"
./3ed090f2dde306e5e9f7200f1022a2c3
./ebd9863a73a5ef22344550a650d169a1
./edbdb765d87586fda75c4287a1e9ea1e
./d9e39bfe0a907ffb580a975d8c8719d2
./2b9cc942c04a8063bd8d4d8fd98814d9
./f5938dd24367ffaf766ef99928660786
./a51accbbf14c8a05cb82caa7d8bec0c6
./0820fb50b412f8e40f63b3bea12e9fb5
./53ef22110569d46b445a1e908a7ae88f
./61ee21f83a33b91674926daf70c34947
Try to open them
me#host:~/Downloads$ find . -type f -iregex "./[^.]*" | xargs xdg-open
xdg-open: unexpected argument './ebd9863a73a5ef22344550a650d169a1'
Try 'xdg-open --help' for more information.
me#host:~/Downloads$ find . -type f -iregex "./[^.]*" -print0| xargs -0 xdg-open
xdg-open: unexpected argument './ebd9863a73a5ef22344550a650d169a1'
Try 'xdg-open --help' for more information.
What's the problem with my usage of xdg-open?
Your problem is that xdg-open does not accept more than one argument, meaning that you can open only one file with it. This seems to be by design, as there are different underlying commands for opening files in different distros, and some of them accept only one argument.
If you are designing distribution-specific script, then you might want to try to find out what command xdg-open invokes. In Ubuntu MATE 16.04 it is gvfs-open, which in turn accepts multiple arguments. I found out this by feeding malformed filepath to xdg-open, as I (yet again) tried to open two files with it. Malformation I used was simply just two files with their paths, separated by comma, no spaces. This was accepted by xdg-open, but gvfs-open complained in return, exposing itself.
If you are designing distribution-independent script, then you may want to look for a solution from here: https://askubuntu.com/questions/356650/how-to-open-multiple-files-with-the-default-program-from-terminal/

Wild cards search in eclipse

The project in our company includes a variety of files. Many a times, it becomes necessary to search all but a few file types. Is there a way to exclude some extensions while doing a searching *.* file search.
One way I know of is to do it via resource filters, but then those exclusions become permanent. What I want is to search for *.*, while removing say *.jsp or *.sql or *.cpp files on the fly.
Thanks,
Ron
You do not mention how you are performing the searches. Personally, I am quite comfortable with the Unix command line, so I have found that having a couple of terminals open on the directory of my Eclipse workspace always comes handy.
On the shell command line, using find and sort to show all files under the current directory:
$ find -type f | sort
./a/a0.txt
./a/a1.doc
./b/b0.rtf
./b/b1.cpp
./b/b2.jsp
./c/c0.jsp
./c/c1.sql
./c/c2.cpp
To show all files except for those matching *.cpp:
$ find -type f ! -name '*.cpp' | sort
./a/a0.txt
./a/a1.doc
./b/b0.rtf
./b/b2.jsp
./c/c0.jsp
./c/c1.sql
To show all files except for those matching *.cpp or *.jsp:
$ find -type f ! -name '*.cpp' ! -name '*.jsp' | sort
./a/a0.txt
./a/a1.doc
./b/b0.rtf
./c/c1.sql
To show all files matching ?1.* except for those matching *.sql:
$ find -type f -name '?1.*' ! -name '*.sql' | sort
./a/a1.doc
./b/b1.cpp
find is the standard Unix command line utility for file searching. Unfortunately, while some of its options are standardized, others are different among the various Unix-like operating systems. You should probably have a look at its manual page (man find) to find out the options that your version of find accepts. The manual page I linked to is for GNU find, which is what most (all?) Linux distributions come with.
If you use Eclipse itself to perform the searches, you can do the following:
Click on Search in the menu bar
Select File
A File Search dialog will pop-up
Click on the Choose button next to the File name patterns textbox
Click on Select all - then remove the check-mark from those extensions you wish to exclude, making sure to exclude *.* as well
A pattern list will appear in the File name patterns textbox
Click Search and a new view with the search results will appear
Disclaimer: this is on Eclipse 3.7.1
This method does not seem to be as powerful as using find, but it offers better integration with Eclipse.

How do I do a recursive find & replace within an SVN checkout?

How do I find and replace every occurrence of:
foo
with
bar
in every text file under the /my/test/dir/ directory tree (recursive find/replace).
BUT I want to be able to do it safely within an SVN checkout and not touch anything inside the .svn directories
Similar to this but now with the SVN restriction: Awk/Sed: How to do a recursive find/replace of a string?
There are several possiblities:
Using find:
Using find to create a list of all files, and then piping them to sed or the equivalent, as suggested in the answer you reference, is fairly straightforward, and only requires scanning through the files once.
You'd use one of the same answers as from the question you referenced, but adding -path '*/.svn' -prune -o after the find . in order to prune out the SVN directories. See this question for a discussion of using the prune option with find -- although note that they've got the pattern wrong. Thus, to print out all the files, you would use:
find . -path '*/.svn' -prune -o -type f -print
Then, you can pipe that into an xargs call or whatever to do the individual replacements, as suggested in the question you referenced. There is a lot of discussion there about different options, which I won't reproduce here, although I prefer the version from John Zwinck's answer:
find . -path '*/.svn' -prune -o -type f -exec sed -i 's/foo/bar/g' {} +
Using recursive grep:
If you have a system with GNU grep, you can use that to find the list of files as well. This is probably less efficient than find, but it does allow you to only call sed on the files that match, and I personally find the syntax a lot easier to remember (or figure out from manpages):
sed -i 's/foo/bar/g' `grep -l -R --exclude-dir='*/.svn' 'foo' .`
The -l option causes grep to only output the list of file names, rather than the matching lines.
Using a GUI editor:
Alternately, if you're using windows, do what I do -- get a copy of the NoteTab editor (available in a free version), and use its search-and-replace-on-disk command, which ignores hidden .svn directories automatically and just works.
Edit: Corrected find pattern to */.svn instead of .svn, added more details and some other possibilities. However, this depends on your platform and svn version: .svn without */ may be required in some cases, like on CentOS 7.
How about this?
grep -i "search_string" `find "*.some_extension"`
That is halfway solution to finding a search_string within files that have a specific extension....once you know the files that has the string, can be easily modified by piping it into sed....

Translate a Unix1Liner to PowerShell

I would like to translate the following Unix 1 Liner to PowerShell.
Synopsis of the command:
This command will search recursively form the PWD (pressent working directory) for any file with the extenstion .jsp, and look inside the file for a simple string match of 'logoutButtonForm'. If it finds a match, it will print the file name and the text that it matched.
find . -name "*.jsp" -exec grep -aH "logoutButtonForm" {}\;
I am new to power shell and have done some googling/binging but have not found a good answer yet.
ls . -r *.jsp | Select-String logoutButtonForm -case
I tend to prefer -Filter over -Include. Guess I never trusted the -Exclude/-Include parameters after observing buggy behavior in PowerShell 1.0. Also, -Filter is significantly faster than using -Include.

How can you search only filenames by find? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
This question is based on the answer.
I run at home
find -- ./ Desktop
I understand the command as
find without parameters
at the current directory that is home (= /Users/masi/)
find the folder name Desktop at the current directory
How do you read the command?
The answer to your question in the title is
$ find . -type f
Now, keep in mind that
$ find -- ./ Desktop
will return the files in Desktop twice.
In your example, "--" says to stop looking for further options. Everything else after that is a path, so it finds anything else matching that. And since "./" means "the current directory" it matches everything under the current directory (the Desktop will cause that directory, as well as anything inside it, to be reported twice.)
You probably want something like:
find ./Desktop -type f
Which will find any files inside the ./Desktop directory, that is a file (not directories, symbolic links, etc...)
I know that manpages can be quite technical sometimes, but "man find" will give you a wealth of other options that might help, as well as a few examples that may help with common problems.
I think what you want is:
find ./ -name Desktop
Well, you can pass multiple directories to search to find:
$ find --help
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
[...]
Note the "[path...]" indicating you can specify multiple paths.
So your example will find all files and directories under ./ (current dir) and under Desktop.