Learn to Code via Tutorials on Repl.it!

← Back to all posts
Finding files in Replit, Linux, and UNIX
h
CodeLongAndPros

Finding files in repl.it with GNU findutils

Sometimes you want a little more than a "search box".
Say someone dumps a tarball into your repl and adds tons of files.
I don't know about you, but this is what I'd do:

What is GNU find?

GNU find is a tool that by default, "selects" all the files in a directory.
So if we take an example directory (my wallpapers) and run find we see:

Find takes options, of which there are four types:
- Modifiers, which change the operation of the program for the whole file. (Example: -print)
- Tests, which return a boolean (Example: -name)
- Actions, which return a number but do something else (Example: -exec)
- Operators, which connect other options: (Example: -and)
You use find by entering find [paths] [options].
Find defaults to your pwd if you provide no path.

Now let's start.
First, make a new bash repl and use the REPL (not the repl) to enter these commands.

You can — er do I want to share my wallpapers - ah who cares - - download this tarball and extract it using tar xvf -8Ul.xz.

Allons-y!

Basic operations

There are a couple of tests which are the most common.

By name

To filter files by name, use -name.

You can use wildcards like * (which matches 0 or more chars) and ? (matches exactly 0 or 1 char).

For example, to get all hidden files:

find -name ".*":

Or to find all hidden PNG wallpapers starting with ani:

find -name '.ani*.png'

To ignore case, use -iname.
find -name '.ani*.png' and find -iname '.Ani*.PNg' return the same thing (if you have the listing above).

By path

To filter by using a path, use -path

The difference with -path and -name is that the content of basename is what is checked.

So if I do find -name /home/swl/wallpapers/.ani?.png, I get nothing, because a file cannot have a / in it's name.

But with -path it does work.

Again, -ipath ignores case.

By regex.

To search a path — not a filename - by regex, use -regex.

For an explanation of the syntax, go to the GNU emacs manual

Once more: use -iregex to ignore case.

You can set the regex type by using -regextype

‘emacs’
Regular expressions compatible with GNU Emacs; this is also the default behaviour if this option is not used.
‘posix-awk’
Regular expressions compatible with the POSIX awk command (not GNU awk)
‘posix-basic’
POSIX Basic Regular Expressions.
‘posix-egrep’
Regular expressions compatible with the POSIX egrep command
‘posix-extended’
POSIX Extended Regular Expressions

This only affects -regex lines placed after it, so put it at the start.

I can't think of an example here

By access/modify/chmod time

So there are three types of times find can filter by:
- Access time: The time the file was last read
- Change time: The time the permissions/owner of the file changed
- Modified time: The time the file was last written to
You can filter in two ways: by day or by minute.
To search by 24-hour block, use either:
- -atime
- -ctime
- -mtime
For ?time, 0 means less than 24 hours, 1 means more than 24 and less than 48, etc.

To filter by minute:
- -amin
- -cmin
- -mmin
-
For example, to file all files accessed less than 5 minutes ago:
find -amin -5

You can also give -daystart at the beginning of the command to make -?time to work from the start of the day and not 24 hours ago.

For example, to see all files you used today:
find / -daystart -atime 0

When giving an integer argument to a test, you can use +n to mean more than n, -n to mean less than n, and n to mean n.

By size

To filter by size, use -size n.
You'll probably want to add a suffix, since the default units is 512 bytes.

The suffixes are:
- b: 512 byte blocks
- c: one byte
- w: two bytes
- k: kibibytes (1024 bytes)
- M: mebibytes (1024 kibibytes)
- G: gibibytes (1024 mebibytes)
Note that 1 Gigabyte does not equal one Gibibyte.
If you're searching for a 2 gigabyte file you'll want about 1907M, not 2G.
As an example, I want to find all file greater than one MiB in my wallpapers:

You can also use -empty, which returns true if the file has no contents.

By user

To filter by user or group, use -user or -group.
You can also use -uid or -gid, which support ranges...

So to find all wallpapers owned by me:

By permissions

To filter by permissions, use -readable, -writable or -executable.
You can also use -perm (which is actually the only standard one)
You pass the usual chmod octal triplet into -perm, like 644, 755 or 777
To find all wallpapers I can write to:

Directory stuff

You can control directory usage with a couple of options, the most common being -maxdepth and -prune

-prune means that if the file is a directory, don't descend into it.
-maxdepth x means to stop after doing down x directories.

Boolean stuff

Find is kind of like a DSL (domain specific language (but it's not TC)).
You can use boolean operators, like NOT, AND, and OR.

For example, to find all files that end with .iso or are greater than 2 Gibibytes:
find -name '*.iso' -or -size +2G
(note that -o is the same as -or)

You can also use -not, ! (you may need to quote it)
By default, each option has an implicit and between it. find -name '*.iso' -mmin -60 is the same as find -name '*.iso' -a (or -and) -mmin -60

Actions on the found files

After finding the files, having a list is cool 'n all, but we may want to do something with it.

Showing found files

There are four ways to show files: -print (the default), -print0 (same as -print but with a \0 instead of \n), -fprint [file] (prints to file), and fprint0 [file] (prints to file with \0)

You can also use -ls to get more info, and -fls to ls to a file

You can use -printf, but that's an "advanced topic" and beyond the (right now, 1151 words I have here).
See more at the man page

Running commands on the file

There are two ways to run a command on a file:
-execdir, and -exec.

-execdir first cd's to the found files, and then runs the command
-exec just runs the command on the relative path.

You can invoke this two ways:
Let's say I want to view all of my wallpapers. I can either do this:
find -name '.ani?*' -o -name '*.jpg' -exec feh {} \;
({} is replaced by the filename), but then one window of feh (my image viewer) opens for each file.

If, instead of the \; (which is escaped to save it from the shell, so find can get it), we use a +?
You see, a ; runs the command once for each file, and the + expands to a list of all the files and runs the command once.
This is also better for performance:
Running find -type f -exec sha256sum {} \; gives us:

versus

Removing files

To remove a found file, use -delete.
For example:
find -empty -delete

And that's about it!
To learn more, read the fine manual

This tutorial was made with the help of Magical Mystery Tour, Sgt. Pepper's Lonely Hearts Club Band and Vim
Voters
Ibnutsany
vcszanelien
Marti2
mkhoi
TsunamiOrSumth
iocoder
FranklinStopar
JBloves27
EpicGamer007
programmeruser
Comments
hotnewtop
infocyber

I Love You Man Thanks For That

DennisGG

Thanks for posting.

firefish

This is cool - I've been doing ls -laR | fgrep for ages.

CodeLongAndPros

@firefish Everyone does it at some point

aaryanporwal

Install fzf in linux/unix systems, find can be a pain and is not newbie friendly at all

CodeLongAndPros

@aaryanporwal The thing is that FZF is not posix, whereas find is going to be on most systems

[deleted]

pog

HahaYes

wowie so cool

EpicGamer007

@HahaYes omg ur back

HahaYes

@EpicGamer007 :0 I'm back

CodeLongAndPros
HahaYes