Wednesday, August 5, 2009

Remove path from find result in Bash


Find all .sh files from current directory.

$ find . -name "*.sh"

./als.sh
./engine/a.sh
./engine/mysc.sh
./tools/new/slv.sh
./tools/instant-parse/iparse.sh

Now if we need to remove the path part from the above find command output:

$ find . -name "*.sh" -exec basename {} \;

als.sh
a.sh
mysc.sh
slv.sh
iparse.sh


Same as

$ find . -name "*.sh" | xargs -i basename {}

And using sed:

$ find . -name "*.sh" | sed 's!.*/!!'

i.e. replace all characters until last / by nothing (here ! is used as the sed delimiter instead of the usual /)

9 comments:

Shahriar75 said...

>>>>Find all .sh files from current directory.

$ find . -name "*.sh"

./als.sh
./engine/a.sh
./engine/mysc.sh
./tools/new/slv.sh
./tools/instant-parse/iparse.sh

Hi,
What should be the command if you want to remve all the .sh files from above output? This means, you want to remove als.sh, a.sh, mysc.sh, slv.sh and iparse.sh and you want to get output as:

./
./engine/
./engine/
./tools/new/
./tools/instant-parse/

Thanks!

Shahriar75 said...

$ find . -name "*.sh"
./als.sh
./engine/a.sh
./engine/mysc.sh
./tools/new/slv.sh
./tools/instant-parse/iparse.sh

Hi,
What should be the command for output (you want only the directory name with file name with *.sh)?

So the output:

./
./engine/
./engine/
./tools/new/
./tools/instant-parse/

Shahriar75 said...

I already wrote the right code.

Unknown said...

@Shahria's Blog:

You can use one of the following:

1)
find . -name "*.sh" -exec rm -f {} \;

2)
find . -name "*.sh" | xargs rm -f

3)
find . -name "*.sh" | while read file;
do
rm -f $file ;
done

4) for file in $(find . -name "*.sh");
do
rm -f $file ;
done

Keep in touch.

Shahriar75 said...

Thanks!

I usd this:

find src -name '*msgs.msg' > Msg_File_list

sed 's/[^\/]\+$//' Msg_File_list > Removal_List

then do other tasks......

Unknown said...

@Shahria's Blog:
Hey, I misunderstood your requirement. I assumed you were trying to remove the files actually.

here is a solution using awk:

$ cat file.txt
./als.sh
./engine/a.sh
./engine/mysc.sh
./tools/new/slv.sh
./tools/instant-parse/iparse.sh

$ awk 'BEGIN{FS=OFS="/"}{$NF=""}{print}' file.txt

Output:
./
./engine/
./engine/
./tools/new/
./tools/instant-parse/

Shahriar75 said...

Thanks!

What does it mean by:

FS=OFS="/"}{$NF=""}{

Unknown said...

@Shahria's Blog:

awk 'BEGIN{FS=OFS="/"}{$NF=""}{print}' file.txt

FS = field separator
OFS = output field separator
NF = number of fields in the current record (line)

So $NF prints the last column in a record (line)

in this case I am removing the last field by
$NF=""

Please try the following two awk one liners:

awk -F "/" '{print NF}' file.txt

awk -F "/" '{print $NF}' file.txt

Please let me know if you have any doubt/question. Thanks.

Anirudh said...

Using GNU find we can determine all the directories that contain atleast 1 *.sh file
as given below.

find . -type d -exec sh -c '
case $(find "$1" -maxdepth 1 -type f -name "*.sh" -print -quit) in "") false;; esac
' {} {} \; -print

© Jadu Saikia www.UNIXCL.com