2
1
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.
2
1
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.
7
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.
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.
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.
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.
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.
No, no. There are no files "*.jpeg", they don't have format in name. I can know its name using 'file' command. – diego9403 – 2015-08-15T06:45:10.277
@adrian OK, OK. See updated answer. – John1024 – 2015-08-15T06:51:48.107
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 – 2015-08-15T07:22:05.133
@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 – 2015-08-15T07:26:33.750
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 – 2015-08-15T07:53:07.143
@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 – 2015-08-15T08:00:28.483
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 – 2015-08-15T09:08:29.957
$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 – 2015-08-15T18:43:58.210
I never used "none". What that mean? – diego9403 – 2015-08-17T08:08:20.307
@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 – 2015-08-17T18:42:48.740
Where did you learn to it? – diego9403 – 2015-08-21T14:19:20.467
@adrian One can learn a lot about bash/shell by reading the stackexchange sites and also Greg's FAQ.
– John1024 – 2015-08-21T18:03:57.653Is it possibility to use mkdir with Pipeline? – diego9403 – 2015-08-22T06:58:23.683
@diego9403 Yes, particularly if used with xargs
. – John1024 – 2015-08-22T07:23:51.343
Please, look http://superuser.com/questions/961036/copy-files-to-other-folder-find.
– diego9403 – 2015-08-22T09:21:26.003I 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 – 2015-08-22T15:36:42.973
1
possible duplicate of How to delete all files in a directory except some?
– LPChip – 2015-08-15T06:49:45.4402
That question, 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
– John1024 – 2015-08-15T06:54:43.293file
command.