3

I know that Windows explorer can colorize the NTFS compression state of a file, in both the regular and search views.

How can I specifically filter/search for files that are compressed or uncompressed on NTFS level?

Preferably a solution that works in Windows XP and higher (there are quite a few hardware devices for which no drivers are available for anything Vista and up).

Since Windows Search is too CPU intensive I'd like a solution without that as well.

6

Command-line interface

Windows XP doesn't provide a way to list compressed files out of the box, and even the advanced search methods aren't designed for such tasks. The command prompt comes to the rescue:

cd /d "C:\Some folder"
compact | findstr /c:" 1 C"

The cd command is simply used to navigate to the target directory. When the compact command is run without parameters it will list all files along with their compression details, if any. The output can be then filtered by redirecting it to findstr. For what is worth, this method should work even on Windows 2000.

Still, the output is quite verbose. To strip out the extra information some more work is required:

for /f "tokens=9,*" %A in ('"compact | findstr /c:" 1 C" "') do @dir /b "%A*%B" 2>nul

The command above will display compressed file names only. The dir command will help validating the file names to avoid false positives (e.g. those containing the string 1 C in their name).

Additional parameters you can use are:

  • /s Applies the command to all subfolders.
  • /a Displays hidden or system files.

Note that those parameters have to be used both for compact and dir commands, if needed.

To list uncompressed files, you can use the /v parameter of the findstr command to reverse the filter, and change the tokens value to 8 (that's because uncompressed files don't have the C marker, which affects the string tokenization).

Further reading


Advanced Query Syntax

Windows Search queries are specified in Advanced Query Syntax (AQS) which supports not only simple text searches but provides advanced property-based query operations as well.

Source: Windows Search - Advanced Query Syntax

AQS was first introduced with Windows Desktop Search, which was later improved and integrated into Windows Vista as Windows Search. You need to install it separately in earlier operating systems.

The following query will list all files which are have the archive attribute set and are compressed. It works in Windows XP, Vista and 7. It should also work in Windows 8.x, although I didn't test.

System.FileAttributes:(2080)

In English locales you can also use:

attributes:(2080)

Here's a list of the most useful values:

FILE_ATTRIBUTE_READONLY = 1
FILE_ATTRIBUTE_HIDDEN = 2
FILE_ATTRIBUTE_SYSTEM = 4
FILE_ATTRIBUTE_ARCHIVE = 32
FILE_ATTRIBUTE_COMPRESSED = 2048
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192

In the example above I combined FILE_ATTRIBUTE_ARCHIVE and FILE_ATTRIBUTE_COMPRESSED: 32 + 2048 = 2080.

You can search any combinations by using the logical OR operator. For example, to search compressed files which are either read-only or not:

System.FileAttributes:(2080 OR 2081)

To invert the search results you can use the NOT operator:

System.FileAttributes:NOT(2080 OR 2081)

Further reading

8
  • Thanks. Too bad it is not supported in XP and Windows 2003 Server (most Windows XP drivers also work in Windows 2003 Server R2 which has EOL next year). I will create another answer (and not accept it) describing how to do the search on the command-line. Mar 22 '14 at 18:16
  • @JeroenWiertPluimers In the original question you didn't specify the target operating system(s), so I only considered the newest ones. As for Windows XP, the most basic features were backported through Windows Search 4.0.
    – and31415
    Mar 22 '14 at 18:24
  • Sorry for that, and Search is to CPU intensive that I'd never consider it. Will make a new edit to the question. Mar 22 '14 at 18:26
  • 1
    @JeroenWiertPluimers I've updated my answer to include a command-line method without third party software.
    – and31415
    Mar 22 '14 at 19:31
  • 1
    @JeroenWiertPluimers I did test it using a non-US installation; granted, I didn't test all languages. While I tried to make the command as locale-independent as possible, it might need to be adapted. Given your requirements, unless you known what's the target OS in advance and you're sure a solution like that would work as expected, a specialized third party tool like FindCompressed is probably the way to go, indeed.
    – and31415
    Mar 24 '14 at 11:08
0

and31415 has posted a nice solution for Windows Explorer that works at least in Windows 7 and up (maybe in Vista, will check that later).

So for older Windows versions like XP and 2003, I've researched for a command-line solution that could generate a list of compressed or uncompressed files.

Compact: nice, but output is hard to parse

The first idea was using compact, which ships with Windows.

And indeed it can list files (enclose parameters in double quotes when they contain spaces):

compact [filemask] /a /s:[directoryname]

The format is easy to read for humans, but not easy to parse.

FindCompressed has a bug with long path names giving listings like this:

C:\Program Files\VMware\Infrastructure\Virtual Infrastructure Client\Help\en\DRS41\wwhelp\wwhimpl\common\htmlinit3.htm
C:\Program Files\VMware\Infrastructure\Virtual Infrastructure Client\Help\en\DRS41\wwhelp\wwhimpl\common\htmlpagenav.htm
...
C:\Program Files\VMware\Infrastructure\Virtual Infrastructure Client\Help\en\DRS41\wwhelp\wwhimpl\common\html\imagessplash.jpg
C:\Program Files\VMware\Infrastructure\Virtual Infrastructure Client\Help\en\DRS41\wwhelp\wwhimpl\common\imagestoolsbg.gif
...
C:\Program Files\VMware\Infrastructure\Virtual Infrastructure Client\Help\en\DRS41\wwhelp\wwhimpl\common\scriptsunidata.js

So it cuts parts of the files or directories when the names get too long.

#FindCompressed: nice, output first/last line needs to be stripped

Exodus Development wrote the command-line tool FindCompressed. Without parameters, it finds compressed files. With the -su parameter, it finds uncompressed files. Enclose [directoryname] in double quotes when it contains spaces.

FindCompressed.exe -su [directoryname]

FindCompressed has one drawback: it always starts output with this line where # is [directoryname]:

Recursive search of compact #.

and ends with a line like this:

Found # uncompressed files in # items examined. 

The lines between those contain a full path to the uncompressed or compressed filename.
That is easy to parse.

0

Since compact shows a C on a fixed position:

134217728 : 0 = 1.0 a 1 C BigFile.Dummy 123456789012345678901234567890123 = 33th position indicates if it is NTFS compressed.

Since all compressed files are listed by compact with a C in the 33th character (at least on where i run it, maybe other languages are different), maybe this command can help:

compact /A | findstr /R ^................................C

/R indicates that the following is a regular expression ^ is to indicate look from beggining of line The 32 dots for ignoring 32st charaters of the line Then the C to indicate must look for a C at the 33th position, that indicates it is NTFS compressed

What it does is list all files and then filter by looking for a C on the 33th position from the begining of the line.

If want recursive, use a for loop that list all directories and run that command on each, like this big sample command (if typed directly on the command line):

(CD "C:\YourBaseDir\" && ECHO Listing NTFS compressed files and folders:  && (compact /A /I | findstr /R ^................................C) && for /F "delims=" %a in ('DIR /AD/B/S') do @(CD "%a" && ECHO Listing NTFS compressed files and folders on: "%a" && (compact /A /I | findstr /R ^................................C)) & CD "C:\YourBaseDir\")

If you put the command inside a BATCH file, the %a must double the %, so must be like this (all in one big line):

(CD "C:\YourBaseDir\" && ECHO Listing NTFS compressed files and folders:  && (compact /A /I | findstr /R ^................................C) && for /F "delims=" %%a in ('DIR /AD/B/S') do @(CD "%%a" && ECHO Listing NTFS compressed files and folders on: "%%a" && (compact /A /I | findstr /R ^................................C)) && CD "C:\YourBaseDir\")

Or for better reading on a BATCH file:

@ECHO OFF
CD "C:\YourBaseDir\"
ECHO Listing NTFS compressed files and folders:
compact /A /I | findstr /R ^................................C
for /F "delims=" %%a in ('DIR /AD/B/S') do @(
 CD "%%a"
 ECHO Listing NTFS compressed files and folders on: "%%a"
 compact /A /I | findstr /R ^................................C
)
CD "C:\YourBaseDir\"

Warning: Compact will also show compressed folders, to avoid them a double for is needed.

The result is like this:

Listing NTFS compressed files and folders:
        0 :         0 = 1.0 a 1 C a
134217728 :         0 = 1.0 a 1 C BigFile.Dummy
Listing NTFS compressed files and folders on: "D:\Temp\a"
        0 :         0 = 1.0 a 1 C b
134217728 :         0 = 1.0 a 1 C Other.Dummy
Listing NTFS compressed files and folders on: "D:\Temp\a\b"
134217728 :         0 = 1.0 a 1 C Another.Dummy

Hope that helps, it is based on findstr allowing regular expresions, so please adapt the regular expression to you OS version and language.

This would be for showing only files (not folders) on the result listing (inside a BATCH file with good reading):

@ECHO OFF
CD "D:\YourBaseDir\"
ECHO Listing NTFS compressed files:
for /F "delims=" %%a in ('DIR /A-D/B') do @(
 compact /A /I "%%a" | findstr /R ^................................C
)
for /F "delims=" %%a in ('DIR /AD/B/S') do @(
 for /F "delims=" %%b in ('DIR /A-D/B "%%a"') do @(
  ECHO Listing NTFS compressed files on: "%%a\"
  compact /A /I "%%a\%%b" | findstr /R ^................................C
 )
)

The trick to not show folders is to use a specific FOR to proccess only the files /A-D parameter on the FOR; at the cost of calling compact/findstr for each individual file.

And please note this one does not do CD to change to the directory... it passes the full path to the file to compact as a parameter... warning with long paths !!!

The result is then like this (no folders shown):

Listing NTFS compressed files:
134217728 :         0 = 1.0 a 1 C BigFile.Dummy
Listing NTFS compressed files on: "D:\Temp\a\"
134217728 :         0 = 1.0 a 1 C Other.Dummy
Listing NTFS compressed files on: "D:\Temp\a\b\"
134217728 :         0 = 1.0 a 1 C Another.Dummy

It also could be improved (as all things on this world) using sed (from GNU for windows) that let cut the file name part of the compact/findstr pair and also with an ECHO that concatenates the path and the sed result.

Hope this can help with the task.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.