Adjusting xargs to accept ls -lh - linux

I want to find files larger than X MB, so I run
find data/ -size +2M
but I need MB next to each file, so I tried this:
find data/ -size +2M | xargs -I '{}' ls -lh '{}'
Above seems to list all files regardless of size, is the xargs part incorrect and it also does a ls on the data/ rather than on the matching files ?
How should the above be written ?
It worked OK if I specify -type f but I think that is not the solution.
find data/ -size +2M -type f | xargs -I '{}' ls -lh '{}'

This might help you sudo find / -size +2M -exec ls -s1h {} \;

Related

UNIX: Use a single find command to search files larger than 4 MiB, then pipe the output to a sort command

I currently have a question I am trying to answer below. Below is what I have come up with, but doesn't appear to be working:
find /usr/bin -type f -size +4194304c | sort -n
Am I on the right track with the above?
Question:
Use a single find command to search for all files larger than 4 MiB in
/usr/bin, printing the listing in a long format. Pipe this output to a sort command
which will sort the list from largest to smallest
I'd fiddle with for -printf command line switch, sth like this:
find YOUR_CONDITION_HERE -printf '%s %p\n' | sort -n: %s stands for size in bytes, %p for file name.
You can trim the sizes later, e.g. using cut, e.g.:
find -type f -size +4194304c -printf '%s %p\n' | sort -n | cut -f 2 -d ' '
But given the fact you need the long list format, I guess you'll be adding more fields to printf's argument.
Related topic: https://superuser.com/questions/294161/unix-linux-find-and-sort-by-date-modified
You are on the right track, but the find command will only output the name of the file, not it's size. This is why sort will sort them alphabetically.
To sort by size, you can output the file list and then pass it to ls with xargs like this:
find /usr/bin -type f -size +4194304c | xargs ls -S
If you want ls to output the file list on a single column, you can replace the -S with -S1. The command would become:
find /usr/bin -type f -size +4194304c | xargs ls -S1
To make your command resistant to all filenames, I would suggest using -print0 (it will separate paths with the null character which is the only one that cannot appear in a filename in Linux). The command would become:
find /usr/bin -type f -size +4194304c -print0 | xargs -0 ls -S1
You could also try
find /usr/bin -type f -size +4194304c -ls | sort -n -k7
and if you want the results reversed then try
find /usr/bin -type f -size +4194304c -ls | sort -r -n -k7
Or another option
find /usr/bin -type f -size +4194304c -exec ls -lSd {} +

shell script that allows to empty a file when it exceeds a certain size

I'm looking for a Linux script that allows to empty the contents of a file when it exceeds a certain size for example 50 kB.
I tried this script :
#!/bin/bash
find /home/walid/Documents -type f -size +50k -exec echo >"{}" \;
but it does not work.
On the other hand it works well for deleting files:
#!/bin/bash
find /home/walid/Documents -type f -size +50k -exec rm "{}" \;
Your redirection (>) takes place before starting find. You probably now have a file of name {}.
I propose to use truncate instead of a redirection for overwriting the file:
find /home/walid/Documents -type f -size +50k -exec truncate --size 0 "{}" \;
A little tweak on your first script should work fine:
#!/bin/bash
find /home/walid/Documents -type f -size +50k -exec sh -c 'echo -n > {}' \;
Give a try to this:
find /home/walid/Documents -type f -size +50k -exec cp /dev/null {} \;
That should work in any *nix like operating system, but also you could give a try to truncate -s 0 filename
find /home/walid/Documents -type f -size +50k -exec truncate -s 0 {} \;

piping empty find result to du through xargs results in unexpected behavior

I came up with a command to find files and print their sizes using find, xargs, and du. I am having a problem when I search for something that does not exist. Using the xargs method, du reports all the folders when something doesn't exist, but I expect it to report nothing because nothing should be found. When using the -exec method it works correctly, but from what I have read and observed in bigger searches, it is less efficient because it repeats the du command for each file found instead of operating on the group of files found. See the section where it mentions -delete: http://content.hccfl.edu/pollock/unix/findcmd.htm
Here is an example. First, this is what is in the directories:
ls
bar_dir/ test1.foo test2.foo test3.foo
ls bar_dir
test1.bar test2.bar test3.bar
Here are two searches where I expect to find results:
find . -name '*.foo' -type f -print0 | xargs -0 du -h
4.0K ./test2.foo
4.0K ./test1.foo
4.0K ./test3.foo
find . -name '*.bar' -type f -print0 | xargs -0 du -h
4.0K ./bar_dir/test1.bar
4.0K ./bar_dir/test2.bar
4.0K ./bar_dir/test3.bar
Here is a search where I expect no results, but instead I get a listing of directories:
find . -name '*.qux' -type f -print0 | xargs -0 du -h
16K ./bar_dir
32K .
If I just use find, it returns nothing (as expected)
find . -name '*.qux' -print0
And if I use the -exec method for du, it also returns nothing (as expected)
find . -name '*.qux' -type f -exec du -h '{}' \;
So what is the matter with the xargs du method when find doesn't find anything? Thanks for your time.
Did you look at du --files0-from - ?
From man du
--files0-from=F
summarize disk usage of the NUL-terminated file names specified in file F; If F is - then read names from standard input
Try like this:
find . -name '*.qux' -type f -print0 | du -h --files0-from -

pipe a command after splitting the returned value

I'm using a find command which results in multiple lines for result, I then want to pipe each of those lines into an ls command with the-l option specified.
find . -maxdepth 2 -type f |<some splitting method> | ls -l
I want to do this in one "command" and avoid writing to a file.
I believe this is what you are looking for:
find . -maxdepth 2 -type f -exec ls -l {} \;
Explanation:
find . -maxdepth 2 -type f: find files with maxdepth at 2
-exec ls -l {} \; For each such result found, run ls -l on it; {} specifies where the results from find would be substituted into.
The typical approach is to use -exec:
find . -maxdepth 2 -type f -exec ls -l {} \;
Sounds like you are looking for xargs. For example, on a typical Linux system:
find . -maxdepth 2 -type f -print0 | xargs -0 -n1 ls -l

List files over a specific size in current directory and all subdirectories

How can I display all files greater than 10k bytes in my current directory and it's subdirectories.
Tried ls -size +10k but that didn't work.
find . -size +10k -exec ls -lh {} \+
the first part of this is identical to #sputnicks answer, and sucesffully finds all files in the directory over 10k (don't confuse k with K), my addition, the second part then executes ls -lh or ls that lists(-l) the files by human readable size(-h). negate the h if you prefer. of course the {} is the file itself, and the \+ is simply an alternative to \;
which in practice \; would repeat or:
ls -l found.file; ls -l found.file.2; ls -l found.file.3
where \+ display it as one statement or:
ls -l found.file found.file.2 found.file.3
more on \; vs + with find
Additionaly, you may want the listing ordered by size. Which is relatively easy to accomplish. I would at the -s option to ls, so ls -ls and then pipe it to sort -n to sort numerically
which would become:
find . -size +10k -exec ls -ls {} \+ | sort -n
or in reverse order add an -r :
find . -size +10k -exec ls -ls {} \+ | sort -nr
finally, your title says find biggest file in directory. You can do that by then piping the code to tail
find . -size +10k -exec ls -ls {} \+ | sort -n | tail -1
would find you the largest file in the directory and its sub directories.
note you could also sort files by size by using -S, and negate the need for sort. but to find the largest file you would need to use head so
find . -size +10k -exec ls -lS {} \+ | head -1
the benefit of doing it with -S and not sort is one, you don't have to type sort -n and two you can also use -h the human readable size option. which is one of my favorite to use, but is not available with older versisions of ls, for example we have an old centOs 4 server at work that doesn't have -h
Try doing this:
find . -size +10k -ls
And if you want to use the binary ls :
find . -size +10k -exec ls -l {} \;
I realize the assignment is likely long over. For anyone else:
You are overcomplicating.
find . -size +10k
I'll add to #matchew answer (not enough karma points to comment):
find . -size +10k -type f -maxdepth 1 -exec ls -lh {} \; > myLogFile.txt
-type f :specify regular file type
-maxdepth 1 :make sure it only find files in the current directory
You may use ls like that:
ls -lR | egrep -v '^d' | awk '$5>10240{print}'
Explanation:
ls -lR # list recursivly
egrep -v '^d' # only print lines which do not start with a 'd'. (files)
only print lines where the fifth column (size) is greater that 10240 bytes:
awk '$5>10240{print}'

Resources