19

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

Benoit
  • 76,634
  • 23
  • 210
  • 236
  • I don't understand what you want. Why don't you want `*` to get expanded? If not, how do you think find shows you the results? – ghostdog74 Oct 22 '10 at 09:32
  • 1
    Because I want `find` to have argv[3] equal to `{'*','.','p','d','f'}`. Find is adult enough to interpret the jokers. – Benoit Oct 22 '10 at 09:33
  • Example: I have `./a.pdf`, `./b/a.pdf`, `./b/b.pdf` ; I run `find . -iname "*.pdf"`. Cmd expands it to `find . -iname a.pdf`, and eventually I do not get `./b/b.pdf` in my results. Of course with a Unix shell, `find . -iname '*.pdf'` gets me all pdf files. – Benoit Oct 22 '10 at 09:36
  • show your batch code in your question to better understand your situation – ghostdog74 Oct 22 '10 at 09:36
  • I run `find . -iname "*.pdf"` and i don't have problems. It will show me all my pdf files... – ghostdog74 Oct 22 '10 at 09:39
  • do you have one or more pdf files in your current directory? – Benoit Oct 22 '10 at 09:41
  • @ghostdog74, I have included real examples for you to be able to figure it out. – Benoit Oct 22 '10 at 09:47
  • [ezwinport](https://sourceforge.net/projects/ezwinports/files/)'s find (4.2.30) is also working as expected, more up to date than UnxUtils perhaps.... – DaveC Dec 19 '20 at 18:45

5 Answers5

18

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'.

user117529
  • 663
  • 8
  • 16
18

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.
Benoit
  • 76,634
  • 23
  • 210
  • 236
  • I got caught by this myself and answered another post (http://stackoverflow.com/questions/33860141/windows-mingw-asterisk-passing-by-argv1-to-string/38098363#38098363) with the answer. For mingw, set a global "int _CRT_glob = 0;" in the same source file as main or Winmain. Globbing is then turned off. It's quite a shock for an experienced programmer the first time you see this happening! – carveone Jun 29 '16 at 11:36
3

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.

zombielei
  • 163
  • 1
  • 8
2

I haven't found anything better than just avoiding wildcard characters

find.exe . -iregex ".+\.pdf" -print
Botz3000
  • 39,020
  • 8
  • 103
  • 127
OCTAGRAM
  • 618
  • 6
  • 12
  • Note: -iregex doesn't work on some versions of gnuwin32 find.exe [due to a bug](http://lists.gnu.org/archive/html/bug-findutils/2005-07/msg00008.html) – user117529 Jul 24 '13 at 20:53
0

@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.

ghostdog74
  • 327,991
  • 56
  • 259
  • 343
  • Same. When I use `C:\gnuwin32\bin\echo.exe "*.txt"` it outputs `a.txt b.txt`. Maybe it is a cmd.exe setting? – Benoit Oct 22 '10 at 10:00
  • ghostdog74: thee [this message](http://www.mail-archive.com/gnuwin32-users@lists.sourceforge.net/msg01582.html). What version of Windows are you using? – Benoit Oct 22 '10 at 11:06
  • I have found a solution for my problem, thank you for helping me diagnose it. Actually, it did not come from cmd.exe which never expands a `*` and lets programs do that themselves, but from `find.exe` which behaves differently on recent versions of Windows. – Benoit Oct 22 '10 at 11:35