2

I am just beginner to shell scripting.

By running below command i am getting output as below

$ cd demo
$ ls
dir1 dir2 dir3 dir4 dir5
$
$find . -mtime -2 -type f -regextype posix-egrep -regex ".*/(dir1|dir2|dir3|dir4|dir5)/.+" -exec ls {} \; > /tmp/basefileslist
./dir1/demo1.sh
./dir2/demo2.sh
./dir3/demo3.sh
./dir4/demo4.sh
./dir5/demo5.sh

I should get output without ./ — I want like below

dir1/demo1.sh
dir2/demo2.sh
dir3/demo3.sh
dir4/demo4.sh
dir5/demo5.sh
mattdm
  • 40,245
afrin
  • 61
  • 1
    Are you using the output of the find command for something, and is that why you want to modify it? The output of find can not generally be safely parsed since Unix filenames can contain newlines. It is therefore better to use find with its -exec predicate to execute whatever it is you need to run on the found files. See also Why is looping over find's output bad practice?. If you don't care about that, then there is nothing stopping you from passing the output through sed 's/..//'. – Kusalananda Jun 02 '23 at 15:41

2 Answers2

4

The ./ in find's output comes from the . argument before the options. Changing the . argument changes the part of the output you're focused on. Given your example, this would produce the output you're asking for:

find dir1 dir2 dir3 dir4 dir5 -mtime -2 -type f -exec ls {} \;

I excluded the regex options because I guessed that they duplicate the action of specifying the subdirectory arguments. The output is:

dir1/demo1.sh
dir2/demo2.sh
dir3/demo3.sh
dir4/demo4.sh
dir5/demo5.sh

In your particular test case (with only five matching subdirs), you can reduce the list of subdirectories to a simple shell glob:

find dir[1-5] -mtime -2 -type f -exec ls {} \;

Or an even shorter glob:

find dir? -mtime -2 -type f -exec ls {} \;

There are many use cases where using find dir1 dir2 dir3 dir4 dir5 or find dir? won't find the desired files like this. But the point of my answer was to show how the arguments before the options will affect the paths in find's output.

Sotto Voce
  • 4,131
3

You can modify the find command to remove the ./ prefix from the output by using the GNU-specific (but then again your -regextype is also GNU-specific) -printf predicate instead of -exec. Here's an example command that should give you the desired output:

find . -mtime -2 \
       -type f \
       -regextype posix-egrep \
       -regex '.*/(dir1|dir2|dir3|dir4|dir5)/.+' \
       -printf '%P\n' > /tmp/basefileslist

In this command, the -printf '%P\n' predicate is used to print the relative path of each file found by find, without the leading ./ prefix. The %P format specifier specifies the relative path (relative to the directory you told it to start from, here .), and \n specifies that each path should be printed on a new line.

After running this command, the output should be similar to the following:

dir1/demo1.sh
dir2/demo2.sh
dir3/demo3.sh
dir4/demo4.sh
dir5/demo5.sh
k.Cyborg
  • 487