{"id":196,"date":"2020-08-18T19:23:47","date_gmt":"2020-08-18T20:23:47","guid":{"rendered":"http:\/\/www.linux-tutorial.info\/?page_id=77"},"modified":"2020-08-22T19:26:16","modified_gmt":"2020-08-22T20:26:16","slug":"this-is-the-page-title-toplevel-30","status":"publish","type":"page","link":"http:\/\/www.linux-tutorial.info\/?page_id=196","title":{"rendered":"Looking for Files"},"content":{"rendered":"\n<title>Looking for Files<\/title>\n<p>\nIn the section on <tutorial id=51>Interacting with the System<\/tutorial> we talked about\nusing the ls command to  look for files. There we had the example of looking in\nthe sub-directory <directory>.\/letters\/taxes<\/directory> for specific files.\nUsing <command>ls<\/command>, command we might have something like this:\n<p>\n<commandexample command=\"ls\">ls .\/letters\/*<\/commandexample>\n<\/p>\n<p>\nWhat if the taxes directory contained a <glossary>subdirectory<\/glossary>\nfor each year for the past five years, each of these contained a <glossary>subdirectory<\/glossary>\nfor each month, each of these contained a <glossary>subdirectory<\/glossary>\nfor federal, state, and local taxes, and each of these contained 10 letters?\n<\/p>\n<p>\nIf we knew that the letter we we&#8217;re looking for was somewhere in the taxes\nsubdirectory, the command\n<p>\n<commandexample command=\"ls\">ls .\/letters\/taxes\/*<\/commandexample>\n<p>\nwould show us the sub-directories of taxes (federal, local, state), and it would\nshow their contents. We could then look through this output for the file we were\nlooking for.\n<\/p>\n<p>\nWhat if the file we were looking for was five levels deeper? We could keep\nadding wildcards (*) until we reached the right directory, as in:<\/p>\n<question id=\"67\" text=\"Repeated wildcards (i.e. *) with the 'ls' command can be used to search sub-directories.\" \/>\n<p>\n<commandexample command=\"ls\">ls .\/letters\/taxes\/*\/*\/*\/*\/*<\/commandexample>\n<\/p>\n<p>\nThis might work, but what happens if the files were six levels deeper. Well,\nwe could add an extra <glossary>wildcard<\/glossary>. What if it were 10 levels deeper and we didn&#8217;t\nknow it? Well, we could fill the line with wildcards. Even if we had too many,\nwe would still find the file we were looking for.\n<\/p>\n<question id=\"68\" text=\"The -R option to 'ls' does what?\" \/>\n<p>\nFortunately for us, we don&#8217;t have to type in 10 asterisks to get what we\nwant. We can use the <keyinput>-R<keyinput> option to ls to do a recursive listing. The -R&nbsp;\noption also avoids the &#8220;argument list too long&#8221; error that we might get with\nwildcards. So, the solution here is to use the ls command like this:<\/p>\n<p>\n<commandexample command=\"ls\">ls -R .\/letters\/taxes | more<\/commandexample>\n<\/p>\n<p>\nThe problem is that we now have 1,800 files to look through. Piping them\nthrough more and looking for the right file will be very time consuming. If we\nknew that it was there, but we missed it on the first pass, we would have to run\nthrough the whole thing again.\n<\/p>\n<p>\nThe alternative is to have the more command search for the right file for you. Because\nthe output is more than one screen, more will display the first screen and at\nthe bottom display <keyinput>&#8211;More&#8211;<keyinput>. Here, we could type a slash (\/) followed by the\nname of the file and press Enter. Now more will search through the output until\nit finds the name of the file. Now we know that the file exists.\n<\/p>\n<p>\nThe problem here is the output of the <command>ls<\/command> command. We can find out\nwhether a file exists by this method, but we cannot really tell where it is. If you try\nthis, you will see that more jumps to the spot in the output where the file is\n(if it is there). However, all we see is the file name, not what directory it is\nin. Actually, this problem exists even if we don&#8217;t execute a search.\n<\/p>\n<p>\nIf you use more as the command and not the end of a <glossary>pipe<\/glossary>, instead of just\nseeing &#8211;More&#8211;, you will probably see something like\n<\/p>\n<p>\n<screenoutput>&#8211;More&#8211;(16{3f0b0cf5c640d99e599990c4a720721a04ec3a009b1323dd81fc335ceb655a63})<\/screenoutput>\n<\/p>\n<p>\nThis means that you have read 16 percent of the file.\n<\/p>\n<p>\nHowever, we don&#8217;t need to use <command>more<\/command> for that. Because we don&#8217;t want to look\nat the entire output (just search for a particular file), we can use one of three\ncommands that Linux provides to do pattern searching: >, <command>egrep<\/command>, and <command>fgrep<\/command>.\nThe names sound a little odd to the Linux beginner, but <command>grep<\/command> stands for\n<u>g<\/u>lobal <u>r<\/u>egular <u>e<\/u>xpression <u>p<\/u>rint. The other two are\nnewer versions that do similar things. For example, egrep searches for patterns\nthat are full regular expressions and <command>fgrep<\/command> searches for fixed strings and is a\nbit faster. We go into details about the grep command in the section on\n<tutorial id=32>looking through files<\/tutorial>.\n<\/p>\n<p>\nLet&#8217;s assume that we are tax consultants and have 50 subdirectories, one for each <glossary>client<\/glossary>.\n Each <glossary>subdirectory<\/glossary> is further broken down by year and type of tax\n(state, local, federal, sales, etc.). A couple years ago, a <glossary>client<\/glossary>\nof ours bought a boat. We have a new <glossary>client<\/glossary>\nwho also wants to buy a boat, and we need some information in that old file.\n<\/p>\n<p>\nBecause we know the name of the file, we can use <command>grep<\/command> to find it, like this:<\/p>\n<p>\n<commandexample command=\"ls\">ls -R .\/letters\/taxes | grep boat<\/commandexample>\n<\/p>\n<p>\nIf the file is called boats, boat.txt, boats.txt, or letter.boat, the <command>grep<\/command>\nwill find it because grep is only looking for the pattern &#8220;boat&#8221;. Because that\npattern exists in all four of those file names, all four would be potential\nmatches.\n<\/p>\n<p>\nThe problem is that the file may not be called boat.txt, but rather\nBoat.txt. Remember, unlike <glossary>DOS<\/glossary>,\n<glossary>UNIX<\/glossary> is case-sensitive. Therefore, grep sees boat.txt and Boat.txt as different files.\nThe solution here would be to tell grep to look for both.\n<\/p>\n<p>\nRemember our <tutorial id=19>discussion on regular expressions<\/tutorial> in\nthe section on shell basics? Not only can we use regular expressions for file\nnames, we can use them in the arguments to commands. The term\n<glossary>regular expression<\/glossary> is even part of grep&#8217;s\nname.\n<\/p>\n<p>\nWithout going into too many details at this point, regular expressions are similar to the\n&#8220;wild cards&#8221; that are available on most systems. These are most commonly used in file names,\nbut can be used in other contexts such as looking for strings within a file&#8217;s contents. We\ngo into details in the <site id=\"19\">seciont on regular expressions and metacharacters<\/site>\nbut we can look at a couple of simple examples here.\n<\/p>\n<p>\nUsing regular expressions, the command to look for a file containing eiher &#8220;Boat&#8221; or &#8220;boat&#8221;\nmight look like this:\n<\/p>\n<p>\n<commandexample command=\"ls\">ls -R .\/letters\/taxes | grep [Bb]oat<\/commandexample>\n<\/p>\n<p>\nIn this example, what the square brackets ( [ ] ) do is specify a set of possible characters.\nHere the set contains only the two letter &#8216;B&#8217; and &#8216;b&#8217;, but it could have been more, if we\nhad wanted.\n<\/p>\n<p>\nSome of you may already see a problem with this as well. Not only does Linux see a\ndifference between boat.txt and Boat.txt, but also between Boat.txt and\nBOAT.TXT. To catch all possibilities, we would have to have a command something\nlike this:<\/p>\n<p>\n<commandexample command=\"ls\">ls -R .\/letters\/taxes | grep [Bb][Oo][Aa][Tt]<\/commandexample>\n<\/p>\n<question id=\"75\" text=\"What does the -i option to grep do?\" \/>\n<p>\nAlthough this is perfectly correct syntax and it will find the files no matter\nwhat case the word &#8220;boat&#8221; is in, it is too much work. The programmers who\ndeveloped <commadn>grep<\/command> realized that people would want to look for things regardless of\nwhat case they are in. Therefore, they built in the <keyinput>-i<\/keyinput>\noption, which simply says ignore the case. Therefore, the command\n<\/p>\n<p>\n<commandexample command=\"ls\">ls -R .\/letters\/taxes | grep -i boat<\/commandexample>\n<\/p>\n<p>\nwill not only find boats, boat.txt, boats.txt, and letter.boat, but it will\nalso find Boat.txt and BOAT.TXT as well.\n<\/p>\n<p>\nIf you&#8217;ve been paying attention, you might have noticed something. Although\nthe <command>grep<\/command> command will tell you about the existence of a file, it won&#8217;t tell you\nwhere it is. This is just like piping it through <command>more<\/command>. The only\ndifference is that we&#8217;re filtering out something. Therefore, it still won&#8217;t tell\nyou the path.\n<\/p>\n<p>\nNow, this isn&#8217;t grep&#8217;s fault. It did what it was supposed to do. We told it\nto search for a particular pattern and it did. Also, it displayed that pattern\nfor us. The problem is still the fact that the ls command is not displaying the\nfull paths of the files, just their names.\n<\/p>\n<concept id=\"45\" description=\"You can use the 'find' command to search for specific files on your system.\" \/>\n<question id=\"482\" text=\"What command would be best if you were looking for a file 'somewhere' on your system.\" \/>\n<p>\nInstead of <command>ls<\/command>, let&#8217;s use a different command. Let&#8217;s use <command>find<\/command> instead. Just as its name implies, <command>find<\/command> is used to find things. What it finds is files. If we\nchange the command to look like this:<\/p>\n<p>\n<commandexample command=\"find\">find .\/letters\/taxes | grep -i boat<\/commandexample>\n<\/p>\n<p>\nThis finds what we are looking for and gives us the paths as well.\n<\/p>\n<p>\nBefore we go on, let&#8217;s look at the syntax of the <command>find<\/command> command. There are a\nlot of options and it may look foreboding, at first. I find it is easiest to\nthink of it this way:<\/p>\n<p>\n<commandexample command=\"find\">find &lt;starting_where&gt; &lt;search_criteria&gt; &lt;do_something&gt;<\/commandexample>\n<\/p>\n<p>\nIn this case, the &#8220;where&#8221; is <directory>.\/letters\/taxes<\/directory>. Therefore,\n<command>find<\/command> starts its search in the <directory>.\/letters\/taxes<\/directory> directory. Here, we have no search criteria; we\nsimply tell it to do something. That something was to print out what it finds. This is the default\nbehaviour so we do not need to include it specifically. However, if we wanted to, we can have\nspecified <keyinput>-print<keyinput> so <command>find<\/command> prints out what it finds. Because the files it finds all have a path relative to <directory>.\/letters\/taxes<\/directory>, this is included in the output. Therefore, when we <glossary>pipe<\/glossary> it through <command>grep<\/command>, we get the path to the file we are looking for.\n<\/p>\n<p>\nWe also need to be careful because the <command>find<\/command>d command we are using will also\nfind directories named boat. This is because we did not specify any search\ncriteria. If instead we wanted it <i><em>just<\/em><\/i> to look for regular files\n(which is often a good idea), we could change the command to look like this:\n<\/p>\n<question id=\"464\" text=\"What command would you use to find all directories under the current directory starting with a capital letter?\" \/>\n<p>\n<commandexample command=\"find\">find .\/letters\/taxes -type f | grep -i boat<\/commandexample>\n<\/p>\n<concept id=\"76\" description=\"You can search for directories using the -type d option to the 'find' command.\" \/>\n<question id=\"\" type=\"mc\" text=\"What option to 'file' would you use to look only for directories?\" \/>\n<p>\nHere we see the option <keyinput>-type f<keyinput> as the search criteria. This will find all\nthe files of type f for regular files. This could also be a <keyinput>d<\/keyinput>\nfor directories, <keyinput>c<\/keyinput>\nfor character special files, <keyinput>b<\/keyinput> for block special files, <keyinput>l<\/keyinput> for symbolic links and so on. Check out the <command>find<\/command> <glossary>man-page<\/glossary>\nfor other types that you can use.\n<\/p>\n<p>\nThere are many different things that we can use as search criteria for <command>find<\/command>.\nTake a quick look at the <glossary>man-page<\/glossary>\nand you will see that you can search for a specific owner,\ngroups, <glossary>permissions<\/glossary>, and even file names.\n<\/p>\n<p>\nLet&#8217;s make things a little easier by not using <command>grep<\/command>.\nInstead of having grep do the search for\nus, let&#8217;s save a step (and time) by having find do the search for us. The command\nwould then look like this:<\/p>\n<p>\n<commandexample command=\"find\">find .\/letters.\/taxes -name boat<\/commandexample>\n<\/p>\n<p>\nThis will find any file named boat and list its respective path. The problem\nhere is that it will only find the files named &#8220;boat&#8221;. It won&#8217;t find the files\nboat.txt, boats.txt, or even Boat.\n<\/p>\n<p>\nThe nice thing is that <command>find<\/command> also understands regular expressions, so we\ncould issue the command like this:<\/p>\n<p>\n<commandexample command=\"find\">find .\/letters.\/taxes -name &#8216;[Bb]oat&#8217;<\/commandexample>\n<\/p>\n<p>\n(Note that we included the single quote (&#8216;) to avoid the square brackets ([]) from\nbeing first interpreted by the <glossary>shell<\/glossary>.) This is not always necessary,\nbut I like to include it just to be safe.\n<\/p>\n<p>\nThis command tells find to look for all files named both boat and Boat.\nHowever, this won&#8217;t find BOAT. We are almost there.\n<\/p>\n<p>\nWe have two alternatives. One is to expand the find to include all possibilities, as in\n<\/p>\n<p>\n<commandexample command=\"find\">find .\/letters.\/taxes -name &#8216;[Bb][Oo][Aa][Tt]&#8217;<\/commandexample>\n<\/p>\n<p>\nThis will find all the files with any combination of those four letters and\nprint them out. However, it won&#8217;t find <file type=\"\">boat.txt<\/file>. Therefore, we need to change it\nyet again. This time we have\n<\/p>\n<question id=\"69\" text=\"The find command can search for specific files using wildcards.\" \/>\n<concept id=\"102\" description=\"The find command can search for specific files using wildcards.\" \/>\n<p>\n<commandexample command=\"find\">find .\/letters.\/taxes -name &#8216;[Bb][Oo][Aa][Tt]*&#8217;<\/commandexample>\n<\/p>\n<p>\nHere we have passed the <glossary>metacharacter<\/glossary> (*) to find to tell it took find anything\nthat starts with &#8220;boat&#8221; (upper- or lowercase), followed by anything else. If we\nadd an extra asterisk, as in\n<\/p>\n<p>\n<commandexample command=\"find\">find .\/letters.\/taxes -name &#8216;*[Bb][Oo][Aa][Tt]*&#8217;<\/commandexample>\n<\/p>\n<p>\nwe not only get <file type=\"\">boat.txt<\/file>, but also <file type=\"\">newboat.txt<\/file>, which the first example would have missed.\n<\/p>\n<p>\nThis works. Is there an easier way? Well, sort of. There is a way that is easier in the sense\nthat there are less characters to type in. This is:\n<\/p>\n<concept id=\"50\" description=\"You can combine find and grep to look for specific text anywhere on your system.\" \/>\n<p>\n<commandexample command=\"find\">find .\/letters\/taxes | grep -i boat <\/commandexample>\n<\/p>\n<p>\nIsn&#8217;t this the same command that we issued before? Yes, it is. In this particular case,\nthis combination of <command>find<\/command> and <command>grep<\/command> is\nactually the easier solution\nbecause all we are looking for is the path to a specific file. However, these\nexamples show you different options of <command>find<\/command> and different ways to use them. That&#8217;s one\nof the nice things about Linux. There are many ways to get the same result.\n<\/p>\n<question id=\"465\" text=\"What command would you use to find all files under the current directory whose contents were changed in the last 30 minutes?\" \/>\n<question id=\"466\" text=\"What command would you use to find all files under the directory \/var\/log which have not been accessed for the last two months?\" \/>\n<concept id=\"75\" description=\"You can search for files based on their age using the -mtime,-atime, and -ctime options to the find command.\" \/>\n<p>\nLooking for files with specific names is only one use of <command>find<\/command>. However, if you\nlook at the <command>find<\/command> <glossary>man-page<\/glossary>, you will see there are\nmany other options you can use. One thing I frequently do is to look for files that are\nolder than a specific age. For example, on many systems, I don&#8217;t want to hang on to log files that\nare older than six months. Here I could use the <keyinput>-mtime<keyinput> options like this:\n<p>\n<commandexample command=\"find\">\nfind \/usr\/log\/mylogs -mtime +180\n<\/commandexample>\n<\/p>\n<p>\nWhich says to find everything in the <directory>\/usr\/log\/mylogs<\/directory> directory which is older\nthan 180 days (Not exactly six months, but it works.) If I wanted, I could have\nused the <keyinput>-name<\/keyinput> option to have specified a particular file pattern:\n<\/p>\n<p>\n<commandexample command=\"find\">\nfind .\/letters.\/taxes -name &#8216;*[Bb][Oo][Aa][Tt]*&#8217; -mtime +180\n<\/commandexample>\n<\/p>\n<question id=\"\" type=\"mc\" text=\"What option to 'find' would you use to look for files based on the time the file was last modified? \" \/>\n<concept id=\"\" description=\"The '-mtime' option to 'find' is used to look for files based on the time the file was last modified.\" \/>\n<p>\nOne problem with this is what determines how &#8220;old&#8221; a file is? The first answer\nfor many people is that the age of a file is how long it has been since the\nfile was created. Well, if I created a file two years ago, but added new data to\nit a minute ago, is it &#8220;older&#8221; than a file that I created yesterday, but have\nnot changed since then? It really depends on what you are interested in. For log\nfiles, I would say that the time the data in that was last changed is more\nsignificant than when the file was created. Therefore, the\n<keyinput>-mtime<keyinput> is fitting as it bases its time on when the data was changed.\nYou can remember this as the &#8220;modification time&#8221;.\n<\/p>\n<question id=\"\" type=\"mc\" text=\"What option to 'find' would you use to look for files based on the time the file was last accessed? \" \/>\n<concept id=\"\" description=\"The '-atime' option to 'find' is used to look for files based on the time the file was last accessed.\" \/>\n<p>\nHowever, that&#8217;s not\nalways the case. Sometimes, you are interested in the last time the file was just used,\nor accessed. This is when you would use the <keyinput>-atime<\/keyinput> option. This is helpful in\nfind old files on your system that no one has used for a long time.<\/p>\n<question id=\"\" type=\"mc\" text=\"What option to 'find' would you use to look for files based on the time the status of the file was last changed? \" \/>\n<concept id=\"\" description=\"The '-ctime' option to 'find' is used to look for files based on the time the status of the file was last changed.\" \/>\n<p>\nYou could also use the <keyinput>-ctime<keyinput> option, which is based on when the files\n&#8220;status&#8221; was last changed. The status is changed when the permissions or file\nowner is changed. I have used this option in security contexts. For example, on\nsome of our systems there are only a few places that contain files that should\nchange at all. For example, <directory>\/var\/log<\/directory>. If I search on all files that were changed\nat all (content or status), it might give me an indication of improper activity\non the system. I can run a script a couple of times an hour to show me the files\nthat have changed within the last day. If anything shows up, I suspect a\nsecurity problem (obviously ignoring files that are supposed to change.)\n<\/p>\n<p>\nThree files that we specifically monitor are <file type=\"passwd\">\/etc\/passwd<\/file>,\n<file type=\"passwd\">\/etc\/group<\/file> and\n<file type=\"passwd\">\/etc\/shadow<\/file>. Interestingly enough, we <i>want<\/i> to have these files change\nonce a month (\/etc\/shadow). This is our &#8220;proof&#8221; that the root password was\nchanged as it should be at regular intervals. Note that we have other mechanisms\nto ensure that it was the root password that was changed and not simply changing\nsomething else in the file, but you get the idea.  One place you see this\nmechanism at work is your <file>\/usr\/lib\/cron\/run-crons<file> file, which is started from\n\/etc\/crontab every 15 minutes.\n<\/p>\n<question id=\"\" type=\"mc\" text=\"What option to 'find' would you use to look for files based on the time the file was last modified, specified in minutes? \" \/>\n<concept id=\"\" description=\"The '-mtime' option to 'find' is used to look for files based on the time the file was last modified, specified in minutes.\" \/>\n<p>\nOne shortcoming of <keyinput>-mtime<\/keyinput> and the others is\nthat it measures time in 24 hour increments starting from now. That means that\nyou cannot find anything that was changed within the last hour, for example. For\nthis newer versions of <command>find<\/command>\nhave the <keyinput>-cmin<\/keyinput>, <keyinput>-amin<\/keyinput> and <keyinput>-mmin<\/keyinput>\noptions, which measure times in minutes. So, to find all of the files changed within the last\nhour (i.e. last 60 minutes) we might have something like this:\n<\/p>\n<p>\n<commandexample command=\"find\">find \/ -amin -60<\/commandexample>\n<\/p>\n<p>\nIn this example, the value was preceded with a minus sign (-), which means\nthat we are looking for files with a value <i>less<\/i> than what we specified.\nIn this case, we want values <i>less<\/i> than 60 minutes. In the example above,\nwe use a plus-sign (+) before the value, which means values greater that what we\nspecified. If you use neither one, then the time is <i>exactly<\/i> what you\nspecified. <\/p> Along the same vein, are the options &#8211;<keyinput>newer<keyinput>,\n<keyinput>-anewer<keyinput>, <keyinput>-cnewer<keyinput>,\nwhich find files which are <i>newer<\/i> than the file specified.\n<\/p>\n<question id=\"468\" text=\"Because of their special nature, you cannot use the 'find' command to look for device nodes.\" \/>\n<question id=\"\" text=\"Because of their special nature, you cannot use the 'find' command to look for symbolic links.\" \/>\n<concept id=\"51\" description=\"The -exec option to find allows you to execute commands on the files it finds.\" \/>\n<question id=\"77\" text=\"To execute a command on every file found with 'find', what option would you use?\" \/>\n<p>\nNote also that these commands find <i>everything<\/i> in the specified path older or younger\nthan what we specify. This includes files, directories, device nodes and so\nforth. Maybe this is what you want, but not always. Particularly if you are\nusing the <keyinput>-exec<keyinput> option and what to search through each file you find, looking\nfor &#8220;non-files&#8221; is not necessarily a good idea. To specify a file type,\nfind provides you with the <keyinput>-type<keyinput> option. Among the possible file type are:\n<\/p>\n<question id=\"\" type=\"mc\" text=\"What option to 'find' would you use to look for a symbolic link? \" \/>\n<question id=\"\" type=\"mc\" text=\"What option to 'find' would you use to look for a named pipe? \" \/>\n<ul>\n<li>b &#8211; block device\n<li>c &#8211; character device\n<li>d &#8211; directory\n<li>p &#8211; named pipe (FIFO)\n<li>f &#8211; regular file\n<li>l &#8211; symbolic link\n<li>s &#8211; socket\n<\/ul>\n<p>\nAs you might expect, you can combine the <keyinput>-type <\/keyinput>\noption with the other options we discussed, to give you something like this:\n<p>\n<commandexample command=\"find\">\nfind .\/letters.\/taxes -name &#8216;*[Bb][Oo][Aa][Tt]*&#8217; -type f -mtime +180\n<\/commandexample>\n<\/p>\n<question id=\"467\" text=\"What command would you use to find all files under the current directory whose owner is not root?\" \/>\n<question id=\"484\" text=\"What command would you use to find all files under the current directory owned by the user dave?\" \/>\n<concept id=\"77\" description=\"You can search for files and directories owned by a particular user using the -user option to the find command.\" \/>\n<p>\nThe good news <i>and<\/i> the bad news at this point is that there are many, many\nmore options you can use. For example. you can search for files based on their\npermissions (<keyinput>-perm<keyinput>), their owner (<keyinput>-users<keyinput>), their size (-size), and so forth. Many I occasionally use, some I have never used. See the find\n<glossary>man-page<\/glossary> for a complete list.\n<\/p>\n<p>\nIn addition, to the <keyinput>-exec<keyinput>\noption, there are a number of other ones that are applied to the files that are\nfound (rather than used to restrict what files are found). Note that in most\ndocumentation, the options used to restrict the search are called <i>tests<\/i>\nand the options that perform an operation on the files are called\n<i>actions<\/i>. One very simple action is <keyinput>-ls<keyinput>, which does a listing of the\nfiles the same as using the -dils options to the ls command.\n<\/p>\n<p>\nA variant of the <keyinput>-exec<keyinput> action is <keyinput>-ok<keyinput>. Rather\nthan simply performing the action on each  file, -ok with first ask you to confirm that\nit should do it. Pressing &#8220;Y&#8221; or &#8220;y&#8221; will run the command, pressing anything else will not.\n<\/p>\n<p>\nWith what we have discussed so far, you might run into a snag if there\nis more than one criterion you want to search on (i.e. more than one test).\nFind addresses that by allowing you to combine tests using either OR (<keyinput>-o<keyinput> <keyinput>-or<keyinput>)\nor AND (<keyinput>-a<keyinput> <keyinput>-and<keyinput>). Furthermore, you can negate the results of any tests (<keyinput>!<keyinput> <keyinput>-not<keyinput>).\nLet&#8217;s say we wanted to find all of the <glossary>HTML<\/glossary> files that were not owned by the\nuser jimmo. Our command might look like this:\n<\/p>\n<p>\n<commandexample command=\"find\">find .\/ -name *.html -not -user jimmo<\/commandexample>\n<\/p>\n<question id=\"70\" text=\"When using the find command, metacharacters should be protected with what symbol to avoid them being interpreted by the shell?\" \/>\n<p>This brings up an important issue. In the section on\n<tutorial id=22>interpreting the command<\/tutorial>, we talk about the fact that\nthe shell expands wildcards before passing them to the command to be executed. In\nthis example, if there was a file in the current directory ending in .html, the\nshell would first expand the .html to that name <i>before<\/i> passing it to\nfind. We therefore need to &#8220;protect&#8221; it before we pass it. This is done using\nsingle quotes and the resulting command might look like this:\n<p>\n<commandexample command=\"find\">find .\/  -name &#8216;*.html&#8217; -not -user jimmo<\/commandexample> <\/p>\n<p>\nFor details on how quoting works, check out the <tutorial id=20>section on quotes<\/tutorial>.\n<p>\nIt is important to keep in mind the order in which things are evaluated. First,\nnegation (-not ! ), followed by AND (and -a), then finally OR (-o -or). In order\nto force evaluation in a particular way, you can include expressions in\nparentheses. For example, if we wanted all of the files or directories owned by\neither root or bin, the command might look like this:\n<p>\n<commandexample command=\"find\">\nfind \/  \\( -type f -o -type d \\) -a \\( -user root -o -user bin \\)\n<\/commandexample>\n<\/p>\n<p>\nThe requires a little explanation. I said that you would use parentheses to\ngroup the tests together. However, they are preceded here with a\n<glossary>back-slash<\/glossary>. The reason is that the shell will see the\nparentheses and try to execute what is inside in a separate shell, which is not\nwhat we wanted.\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Looking for Files In the section on Interacting with the System we talked about using the ls command to look for files. There we had the example of looking in the sub-directory .\/letters\/taxes for specific files. Using ls, command we &hellip; <a href=\"http:\/\/www.linux-tutorial.info\/?page_id=196\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-196","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/196","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=196"}],"version-history":[{"count":1,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/196\/revisions"}],"predecessor-version":[{"id":613,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/196\/revisions\/613"}],"wp:attachment":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=196"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}