3

I have exercise, in which I have to delete all files, which are not jpeg.

I tried find -type f |xargs file| grep -iv 'jpeg', but it doesn't work.

fixer1234
  • 27,064
  • 61
  • 75
  • 116
diego9403
  • 897
  • 1
  • 12
  • 21
  • 1
    possible duplicate of [How to delete all files in a directory except some?](http://superuser.com/questions/529854/how-to-delete-all-files-in-a-directory-except-some) – LPChip Aug 15 '15 at 06:49
  • 3
    That question, [How to delete all files in a directory except some?](http://superuser.com/questions/529854/how-to-delete-all-files-in-a-directory-except-some), discusses how to delete files _based on the file's name_. This question, by contrast, asks how to delete _based on the file's type_ as reported by the `file` command. – John1024 Aug 15 '15 at 06:54

1 Answers1

8

Deleting based on file mimetype

To delete all non-jpeg regular files in the current directory or its subdirectories, use:

find . -type f -exec bash -c 'file -bi "$1" | grep -q image/jpeg || rm "$1"' none {} \;

This approach is safe for all file names. It will work even if the file names have newlines or other difficult characters in them.

How it works

  • find . -type f

    This starts a find command, restricting the files found to regular files, -type f.

  • -exec bash -c 'file -bi "$1" | grep -q image/jpeg || rm "$1"' none {} \;

    For all the files found, this runs a bash command to test the file's type. In particular, file -bi "$1" | grep -q image/jpeg will return true if file reports that the file has mimetype image/jpeg. The operator || assures that the rm command which follows is executed only for files which failed the jpeg test. Thus, all non-jpeg files are deleted.

Deleting based on file name

To delete all files whose names do not end in .jpeg:

find . -type f ! -name '*.jpeg' -delete

This approach is also safe for all file names. It will work even if the file names have newlines or other difficult characters in them.

How it works

  • find .

    Find all files in the current directory and its subdirectories

  • -type f

    Restrict ourselves only to regular files

  • ! -name '*.jpeg'

    -name '*.jpeg' would find all files whose names end in .jpeg. The exclamation mark, !, however, means negation. So, ! -name '*.jpeg' restricts our search to files whose names do not end in .jpeg.

  • -delete

    This tells find to delete the files that match the above criteria.

Testing

To test the command, leave off the -delete:

find . -type f ! -name '*.jpeg'

This will show you what files would be deleted when the -delete action is used.

John1024
  • 16,593
  • 5
  • 50
  • 45
  • No, no. There are no files "*.jpeg", they don't have format in name. I can know its name using 'file' command. – diego9403 Aug 15 '15 at 06:45
  • @adrian OK, OK. See updated answer. – John1024 Aug 15 '15 at 06:51
  • I didn't find answer. I have to add, that there are a lot of folders in folders, so "ls -l" is not enough.I thought about '-exec', but its accept only one commant and my favorite "|" doesn't work. – diego9403 Aug 15 '15 at 07:22
  • @adrian Look again: I did not use `ls -l`. I used `find` which will search all subfolders. Second, look at __how__ I used `-exec`. The `-exec` command runs a bash shell and the bash shell fuilly supports features like `|` and `||`. – John1024 Aug 15 '15 at 07:26
  • Ok, but I have to know what is the type of files ('jpeg'), that why i should use 'file', but that command make it difficult. After use 'file', i can't use rm to delete files. – diego9403 Aug 15 '15 at 07:53
  • @adrian I added an answer that uses `file` to determine the type. It is used in the `-exec` clause. If your browser doesn't show that, please _reload_ the web page. The argument that I show for the `-exec` clause uses `file` to determine type and then executes `rm` according to the result. You say it is "difficult" but my answer shows how to do it. – John1024 Aug 15 '15 at 08:00
  • Thank you, my master. But I have some questions. What "$1" means. I changed it for "{}" and it works. However I want to know what is it. I used it in bash script, but I suspect is something different. – diego9403 Aug 15 '15 at 09:08
  • `$1` means the same thing as in a script: it is the first argument. Our bash command looks like `bash -c 'commands' none {}`. The `commands` that are run can reference the value of `{}` as `$1`. Done this way, it is safe for all file names. If you change `commands` by replacing `$1` with `{}`, then it will work for simple file names but it will fail if a difficult file name appears. So, don't do that. – John1024 Aug 15 '15 at 18:43
  • I never used "none". What that mean? – diego9403 Aug 17 '15 at 08:08
  • @adrian The `none` is critical for making the code work. When running `bash -c 'commands' arg0 arg1 ...`, bash interprets `arg0` as the (pretend) name of the program that is being run and assigns it to `$0`. Next, `arg1`, the file name in our case, is assigned to `$1`. So, `none` is a placeholder: it is assigned to `$0` which we never use but, without it, `$1` would have the wrong value and the code would fail. – John1024 Aug 17 '15 at 18:42
  • Where did you learn to it? – diego9403 Aug 21 '15 at 14:19
  • @adrian One can learn a lot about bash/shell by reading the stackexchange sites and also [Greg's FAQ](http://mywiki.wooledge.org/BashFAQ). – John1024 Aug 21 '15 at 18:03
  • Is it possibility to use mkdir with Pipeline? – diego9403 Aug 22 '15 at 06:58
  • @diego9403 Yes, particularly if used with `xargs`. – John1024 Aug 22 '15 at 07:23
  • Please, look http://superuser.com/questions/961036/copy-files-to-other-folder-find. – diego9403 Aug 22 '15 at 09:21
  • I have to copy files (which are in lot of folders) to folder with its type. For example files lake.jpg (type jpeg) I have to copy to folder 'jpeg', but this folder is in other parent folder, which name is parametr in script. My command: find ./find -type f -exec bash -c ' file -b "$1"|cut -d " " -f 1 |awk -f wa|xargs cp "$1" ' none {} \; Files are copied, but there is an error: cp: ./find/PDF/20163.32630.27874' and find/PDF 20163.32630.27874' are the same file – – diego9403 Aug 22 '15 at 15:36