添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

However, I need to run this script in Windows, and am trying to find the equivalent command. I have tried

find /c /v C:/inputdirectory/P*

But this throws an error, that /v is not a valid command. Can you please tell me why this isn't working?

*note, the command itself doesn't say "inputdirectory", it has the correct directory, it's just too tedious and private to type out

Try searching for "" , i.e. an empty string; use only backslash as the path separator; and quote the path if it has spaces in it: find /c /v "" "C:\inputdirectory\P*" . Eryk Sun Jun 21, 2018 at 20:07 Cygwin provides a lot of Linux utilities ported to Windows. "Get that Linux feeling - on Windows" . LMC Jun 21, 2018 at 20:38

Courtesy of Eryk Sun :

Try searching for "" , i.e. an empty string; use only backslash as the path separator; and quote the path if it has spaces in it:

find /c /v "" "C:\inputdirectory\P*"
                FIND /C /V is not totally equivalent of wc -l. It emits a string of dashes followed by the file name, then the count. ---------- README.TXT: 41 Whereas, wc -l only emits the count.
– lit
                Jun 21, 2018 at 21:40

Note: If all you need is the line count of a single input file, a simple solution (which loads the whole file into memory) is, e.g., (gc file.txt).Count (gc is a built-in alias for Get-Content).
Faster version: (gc -ReadCount 0 file.txt).Count

From cmd.exe (the Command Prompt / a batch file), which is obsolescent:

  • Use the accepted answer.
  • From PowerShell, you have two options:

  • Option A (suboptimal): Use the accepted answer too, with a small tweak:
  • find --% /c /v "" "C:\inputdirectory\P*"
    

    Note: --%, the stop-parsing symbol, tells PowerShell to pass subsequent arguments through as-is to the target program (after expanding cmd-style environment-variable references such as %USERNAME%, if any).

    In the case at hand, this prevents PowerShell from parsing "" and - mistakenly - neglecting to pass it through to the external target program (find.exe).

    For a summary of PowerShell's highly problematic handling of quotes when calling external programs, see this answer.

    Output from the above find.exe command - and, indeed, any external program, is just text, and in this case it looks something like this:

    ---------- PFILE1.TXT: 42
    ---------- PFILE2.TXT: 666
    

    While this output is easy to grasp for a human observer, it makes subsequent programmatic processing cumbersome, because text parsing is required.

    Using a PowerShell-native command (cmdlet), as described below, offers more flexibility, because PowerShell commands typically emit objects with typed properties, which greatly facilitates subsequent processing.

  • Option B (preferred): Use PowerShell's own Measure-Object cmdlet with the -Line switch:
  • Note: While this command is more verbose than the find solution, it ultimately offers more flexibility due to outputting objects with typed properties, which greatly facilitates subsequent processing; additionally, PowerShell's sophisticated output-formatting system offers user-friendly default representations.

    Get-Item -Path "C:\inputdirectory\P*" -PipelineVariable file | ForEach-Object {
      Get-Content -LiteralPath $file |
        Measure-Object -Line |
          Select-Object @{ Name='File'; Expression={ $file } }, Lines
    

    The above outputs objects that have a .File and .Lines property each, which PowerShell prints as follows by default:

    File                         Lines
    ----                         -----
    C:\inputdirectory\Pfile1.txt    42
    C:\inputdirectory\Pfile2.txt   666
    

    In addition to a nicer presentation of the output, the object-oriented nature of the output makes it easy to programmatically process the results.

    For instance, if you wanted to limit the output to those files whose line count is 100 or greater, pipe to the following Where-Object call to the above command:

    ... | Where-Object Lines -ge 100
    

    If you (additionally) wanted to sort by highest line count first, pipe to the Sort-Object cmdlet:

    ... | Sort-Object -Descending Lines
                    The verbose part of this answer is gross. A more streamlined way is described at superuser.com/questions/959036/… tl/dr:  cat file.txt | Measure-Object -line
    – MarkHu
                    Mar 21 at 21:26
                    @MarkHu, all your command does is (a) replace Get-Content with its cat alias (on Windows), (b) apply Measure-Object -Line to a single input file, and (b) without producing the output that wc -l would. In other words: you're answering a different, much simpler question, and it's no surprise that the solution is shorter. If all you're interested in is knowing a single file's line count, use (cat file.txt).Count
    – mklement0
                    Mar 21 at 21:33
                    @MarkHu, as for the (ls | Measure-Object -line).Lines shown in the linked SU post:   just use (gci).Count - no need for Measure-Object at all. (gci is a built-in alias of Get-ChildItem, as is ls on Windows; however, on Unix-like platforms, ls refers to the external /bin/ls utility).
    – mklement0
                    Mar 21 at 21:45
    

    How can I count the lines in a set of files?

    Use the following batch file (CountLines.cmd):

    @echo off
    Setlocal EnableDelayedExpansion
    for /f "usebackq" %%a in (`dir /b %1`)  do (
      for /f "usebackq" %%b in (`type %%a ^| find "" /v /c`) do (
        set /a lines += %%b
    echo %lines%
    endlocal
    

    Usage:

    CountLines C:/inputdirectory/P*
    

    Further Reading

  • An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
  • dir - Display a list of files and subfolders.
  • find - Search for a text string in a file & display all the lines where it is found.
  • for /f - Loop command against the results of another command.
  • In case it's not obvious, if we type the file through a pipe to find, there's no filename for a summary header, so find just outputs the line count. The inner for /f 'loop' extracts this result and, in this case, adds it to the running total lines for all processed files. – Eryk Sun Sep 7, 2019 at 10:38 This is an interesting exercise in reporting the total line count, summed across multiple files, but that's not what wc -l C:/inputdirectory/P* does; the latter reports the count per input file in the form <count> <file>, which is also what find.exe does directly when file arguments are passed, differences in formatting details aside. – mklement0 Sep 9, 2019 at 2:40

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.