Find all images linux

List all graphic image files with find? [closed]

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.

There are many types of graphic images in this huge archive such as .jpg, .gif, .png, etc. I don’t know all the types. Is there a way with ‘find’ to be able to have it list all the graphic images regardless of their dot extension name? Thanks!

For videos, see the corresponding Q&A here: Ask Ubuntu: How can I find all video files on my system?. For anyone wanting to add a new answer for images, you could probably just add it there as well.

6 Answers 6

find . -name '*' -exec file <> \; | grep -o -P '^.+: \w+ image' 
./navigation/doc/Sphärische_Trigonometrie-Dateien/bfc9bd9372f650fd158992cf5948debe.png: PNG image ./navigation/doc/Sphärische_Trigonometrie-Dateien/6564ce3c5b95ded313b84fa918b32776.png: PNG image ./navigation/doc/subr_1.jpe: JPEG image ./navigation/doc/Astroanalytisch-Dateien/Gamma.gif: GIF image ./navigation/doc/Astroanalytisch-Dateien/deltaS.jpg: JPEG image ./navigation/doc/Astroanalytisch-Dateien/GammaBau.jpg: JPEG image 

Is there a similar approach that can be taken for video? It seems that replacing «image» with «video» skips quicktime and Matroska formats.

@ElderGeek I would run file on some examples and see if there was a piece of text I could grep for. In the image section of the awk solution you could separate patterns with alternation for example /video|image|foo/ would return all files that had the word video, image, or foo in their description from file.

Any ideas on how I can get rid of the : GIF image or : JPEG image and just be left off with the name of the file plus the path so I can pass it to another command as an output?

Note that the \w+ part would exclude results like foo.svg: SVG Scalable Vector Graphics image . To find for example .svg files, change \w+ to .*

For macOS mojave, grep has no -P option, and the output of the file command is very verbose. By the way, it will be better if you could explain your command.

The following suits me better since in my case I wanted to pipe this list of files to another program.

find . -type f -exec file --mime-type <> \+ | awk -F: '' 

If you wanted to tar the images up (as someone in the comments) asked

find . -type f -exec file --mime-type <> \+ | awk -F: '' | tar -cvf /tmp/file.tar --null -T - 

The first oneliner leverages the following commands, find, file, and awk. The second oneliner adds tar. Your best bet is to consult your local man pages for the behavior of your specific system.

before using this command to create tar make sure you have enough free space! (in this case on root partition)

find . -type f -exec file <> \; | grep -o -P '^.+: \w+ image' 

@Selah This command specifies -type f , which would get files but not folders and execute the file command, so it could be a bit quicker than j.holetzeck’s answer.

This command has issue if filename matched ^.+: \w+ image , e.g. hello: fake image . Consider this solution: find . -type f -print0 | xargs -0 bash -c ‘for arg do file -b —mime-type «$arg» | grep -q ‘^image/’ && echo «$arg»; done’ _ . Explanation: 1. file -b output only filetype to avoid filename match ^.+: \w+ image . 2. -print0 | xargs -0 able deal with newline in filename while my other comments not deal with that exotic case. 3. for loop with trailing _ to covers ‘ or $var in filename) 4. —mime-type avoid .psd («I»mage) and .eps (no «image») file type issues.

Читайте также:  Linux mint install nouveau

Grepping or using awk for «image» only will not do it. PSD-files will be identified by «Image» with a capital «I» so we need to improve the regexp to either be case insensitive or also include the capital I. EPS-files will not contain the word «image» at all so we need to also match for «EPS» or «Postscript» depending on what you want. So here is my improved version:

find . -type f -exec file <> \; | awk -F: '< if ($2 ~/[Ii]mage|EPS/) print $1>' 

Update (2022-03-03)

This is a refined version with the following changes:

find . -type f | file --mime-type -f - | grep -F image/ | rev | cut -d : -f 2- | rev 

Below is a more performant solution compared to the chosen answer:

find . -type f -print0 | xargs -0 file --mime-type | grep -F 'image/' | cut -d ':' -f 1 
  1. Use -type f instead of -name ‘*’ since the former will search only files while the latter search both files and directories.
  2. xargs execute file with arguments as many as possible, which is super fast compared to find -exec file <> \; which executes file for each found.
  3. grep -F is faster since we only want to match fixed string.
  4. cut is faster than awk (more than 5 times faster as I can recall).

According to my limited testing my updated invocation executes faster than what you have currently, but I welcome the comments. Your use of xargs reminded me that find does something equivalent. Also the mime-types option to find is a good addition. It does produce a different results from what I had previously, but the biggest plus is it excludes virtual machine images. For an accurate comparison with awk you will need to combine grep piped in to cut since that is doing both of those things. Still awk will provide you more versatility. Thank you.

Should change cut -d ‘:’ -f 1 to rev | cut -d ‘:’ -f 2- | rev to print full filename contains : . e.g. hello : world.jpg

Источник

find and copy all images in directory using terminal linux mint, trying to understand syntax

OS Linux Mint Like the title says finally I would like to find and copy all images in a directory. I found: find all jpg (or JPG) files in a directory and copy them into the folder /home/joachim/neu2:

find . -iname \*.jpg -print0 | xargs -I<> -0 cp -v <> /home/joachim/neu2 
find . -name '*' -exec file <> \; | grep -o -P '^.+: \w+ image' 

My problem is first of all, I don’t really understand the syntax. Could someone explain the code? And secondly can someone connect the two codes for generating a code that does what I want 😉 Greetings and thanks in advance!

5 Answers 5

First, understand that the pipe «|» links commands piping the output of the first into the second as an argument. Your two shell codes both pipe output of the find command into other commands (grep and xargs). Let’s look at those commands one after another:

Читайте также:  Перезагрузить все процессы linux

First command: find

find is a program to «search for files in a directory hierarchy» (that is the explanation from find’s man page). The syntax is (in this case)

In both cases the search directory is . (that is the current directory). Note that it does not just search the current directory but all its subdirectories as well (the directory hierarchy).

The search pattern accepts options -name (meaning it searches for files the name of which matches the pattern given as an argument to this option) or -iname (same as name but case insensitive) among others.

The action pattern may be -print0 (print the exact filename including its position in the given search directory, i.e. the relative or absolute path to the file) or -exec (execute the given command on the file(s), the command is to be ended with «;» and every instance of «<>» is replaced by the filename).

That is, the first shell code (first part, left of the pipe)

searches all files with ending «.jpg» in the current directory hierarchy and prints their paths and names. The second one (first part)

finds all files in the current directory hierarchy and executes

on them. File is another command that determines and prints the file type (have a look at the man page for details, man file).

Second command: xargs

xargs is a command that «builds and exectues command lines from standard input» (man xargs), i.e. from the find output that is piped into xargs. The command that it builds and executes is in this case

Option -I<> defines the replacement string, i.e. every instance of <> in the command is to be replaced by the input it gets from file (that is, the filenames). Option -0 defines that input items are not terminated (seperated) by whitespace or newlines but only by a null character. This seems to be necessary when using and the standard way to deal with find output as xargs input.

The command that is built and executed is then of course the copy command with option -v (verbose) and it copies each of the filenames it gets from find to the directory.

Third command: grep

grep filters its input giving only those lines or strings that match a particular output pattern. Option -o tells grep to print only the matching string, not the entire line (see man grep), -P tells it to interpret the following pattern as a perl regexp pattern. In perl regex, ^ is the start of the line, .+ is any arbitrary string, this arbitrary should then be followed by a colon, a space, a number of alphanumeric characters (in perl regex denoted \w+) a space and the string «image». Essentially this grep command filters the file output to only output the filenames that are image files. (Read about perl regex’s for instance here: http://www.comp.leeds.ac.uk/Perl/matching.html )

The command you actually wanted

Now what you want to do is (1) take the output of the second shell command (which lists the image files), (2) bring it into the appropriate form and (3) pipe it into the xargs command from the first shell command line (which then builds and executes the copy command you wanted). So this time we have a three (actually four) stage shell command with two pipes. Not a problem. We already have stages (1) and (3) (though in stage (3) we need to leave out the -0 option because the input is not find output any more; we need it to treat newlines as item seperators).

Читайте также:  Change directory to root linux

Stage (2) is still missing. I suggest using the cut command for this. cut changes strings py splitting them into different fields (seperated by a delimiter character in the original string) that can then be rearranged. I will choose «:» as the delimiter character (this ends the filename in the grep output, option -d’:’) and tell it to give us just the first field (option -f1, essentialls: print only the filename, not the part that comes after the «:»), i.e. stage (2) would then be

And the entire command you wanted will then be:

find . -name '*' -exec file <> \; | grep -o -P '^.+: \w+ image' | cut -d':' -f1 | xargs -I<> cp -v <> /home/joachim/neu2 

Источник

Find images in a Linux directory based on their resolution

I would like to scan all images in a directory (recursively within sub-folders), and find those with resolution higher than a specific threshold (e.g. say those with resolutions at least 800×600 or if easier, say with width higher than 1000 pixels). Then I would like to log their address in a text file, accompanying their resolution (or [width], [height] for a better formatting). So log.txt would look like this:

/home/users/myuser/test/image1.jpg, 1800, 1600 /home/users/myuser/test/image20.jpg, 2800, 2600 /home/users/myuser/test/image30.jpg, 1500, 1200 

1 Answer 1

Via bash’s recursive glob and ImageMagick’s identify command:

shopt -s globstar identify -format "%f, %w, %h\n" **/*.

Saving such output to file , is just a matter of adding > mylog.txt to previous command, that is

identify -format "%f, %w, %h\n" **/*. > mylog.txt 

From there, you could use awk or perl to compare mylog.txt columns

awk -F ',' '$2 > 800 && $3 > 600' mylog.txt 

awk here uses , as separator for columns, and the usual structure for awk is /PATTERN/ , which defaults to just printing if omitted ; in the particular example above, if the pattern $2 > 800 && $3 > 600 is true, that is it’s the image above desired resolution, you’ll get it printed to the screen.

And probably skipping the log step in between, it would be a little better to just pipe everything:

shopt -s globstar identify -format "%f, %w, %h\n" **/*. | awk -F ',' '$2 > 800 && $3 > 600' > filtered_images.txt 

In case you encounter arguments list too long error, typically find command is better approach for recursively walking the directory tree. The identify can be called through find ‘s -exec flag, and filtering still can be handled by awk :

$ find -type f -regex "^.*\.\(png\|jpg\|jpeg\)$" -exec identify -format "%f, %w, %h\n" <> \; | awk -F ',' '$2 > 800 && $3 > 600' fanart.jpg, 1920, 1080 fanart.jpg, 1920, 1080 globalsearch-background.jpg, 1920, 1080 fanart.jpg, 1280, 720 

As usual, don’t forget to add > log2.txt to save everything to file.

Full path of to the file could be handled in either one of two ways. One, by specifying %d/%f in identify command’s format string, or use find ‘s -printf option. That is either

find -type f -regex "^.*\.\(png\|jpg\|jpeg\)$" -exec identify -format "%d/%f, %w, %h\n" <> \; | awk -F ',' '$2 > 800 && $3 > 600' 
find -type f -regex "^.*\.\(png\|jpg\|jpeg\)$" -printf "%p, " -exec identify -format "%w, %h\n" <> \; | awk -F ',' '$2 > 800 && $3 > 600' 

Источник

Оцените статью
Adblock
detector