Unix Shell - delete ./ from ./filename

This is Interesting: Free IT Magazines  
Home > Archive > Unix Shell > January 2006 > delete ./ from ./filename





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author delete ./ from ./filename
kelly

2006-01-17, 6:05 pm

find output:
../star.c
../encrypt.cl.c
../test.c

I want the final output to be
star.c
encrypt.c
test.c

when I do the cmd below, all the . gets deleted,

find -name "*.c" | tr -d [./]

leaving me with
starc
encryptclc
testc

tx

Chris F.A. Johnson

2006-01-17, 6:05 pm

On 2006-01-17, kelly wrote:
> find output:
> ./star.c
> ./encrypt.cl.c
> ./test.c
>
> I want the final output to be
> star.c
> encrypt.c
> test.c
>
> when I do the cmd below, all the . gets deleted,
>
> find -name "*.c" | tr -d [./]
>
> leaving me with
> starc
> encryptclc
> testc


find -name "*.c" | sed 's|.*/\(.*\)|\1|'


--
Chris F.A. Johnson, author | <http://cfaj.freeshell.org>
Shell Scripting Recipes: | My code in this post, if any,
A Problem-Solution Approach | is released under the
2005, Apress | GNU General Public Licence
parv

2006-01-17, 6:05 pm

in message <43CD6BB7.2080603@some.com>,
wrote kelly ...

> find output:
> ./star.c
> ./encrypt.cl.c

^ ^
^ ^
> I want the final output to be
> star.c
> encrypt.c

^ ^
^ ^
Notice that ".cl" is missing. Typo?


> when I do the cmd below, all the . gets deleted,
>
> find -name "*.c" | tr -d [./]
>
> leaving me with
> starc
> encryptclc

^ ^
^ ^
"cl" reappeared.


tr(1) changes the *all the characters present in string*; use
basename, awk, sed, or even your shell's parameter expansion. Below
is an exmaple of sh (FreeBSD 6) script ...

{ echo ./start.c ; echo ./encrypt.c; } \
| while read f
do
echo ${f#./}
done


- parv

--
As nice it is to receive personal mail, too much sweetness causes
tooth decay. Unless you have burning desire to contact me, do not do
away w/ WhereElse in the address for private communication.

Stachu 'Dozzie' K.

2006-01-17, 6:05 pm

On 17.01.2006, Chris F.A. Johnson <cfajohnson@gmail.com> wrote:
> On 2006-01-17, kelly wrote:
>
> find -name "*.c" | sed 's|.*/\(.*\)|\1|'


What is '\(.*\)' for? sed 's|.*/||' would do the same. And looking at
the sample provided by kelly, `sed s/..//' amd `cut -b3-' also would do
that.

--
Feel free to correct my English
Stanislaw Klekot
Xicheng

2006-01-17, 6:05 pm

kelly wrote:
> find output:
> ./star.c
> ./encrypt.cl.c
> ./test.c
>
> I want the final output to be
> star.c
> encrypt.c
> test.c

what you need is the basename of your files:

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

Xicheng

Chris F.A. Johnson

2006-01-17, 6:05 pm

On 2006-01-17, Stachu 'Dozzie' K. wrote:
> On 17.01.2006, Chris F.A. Johnson <cfajohnson@gmail.com> wrote:
>
> What is '\(.*\)' for?


Good question!

> sed 's|.*/||' would do the same.


True.

> And looking at the sample provided by kelly, `sed s/..//' amd
> `cut -b3-' also would do that.


Only if there was only one level of directory, in which case he
wouldn't need find:

printf "%s\n" *.c | sed 's|.*/||'

--
Chris F.A. Johnson, author | <http://cfaj.freeshell.org>
Shell Scripting Recipes: | My code in this post, if any,
A Problem-Solution Approach | is released under the
2005, Apress | GNU General Public Licence
Stachu 'Dozzie' K.

2006-01-17, 6:05 pm

On 17.01.2006, Chris F.A. Johnson <cfajohnson@gmail.com> wrote:
> On 2006-01-17, Stachu 'Dozzie' K. wrote:
[...][vbcol=seagreen]
>
> Only if there was only one level of directory, in which case he
> wouldn't need find:
>
> printf "%s\n" *.c | sed 's|.*/||'


He wouldn't even need sed in this case ;)

--
Feel free to correct my English
Stanislaw Klekot
Kurt Swanson

2006-01-17, 6:05 pm

kelly <kelly@some.com> writes:
> find output:
> ./star.c
> ./encrypt.cl.c
> ./test.c


> I want the final output to be
> star.c
> encrypt.c
> test.c


> when I do the cmd below, all the . gets deleted,


> find -name "*.c" | tr -d [./]


> leaving me with
> starc
> encryptclc
> testc


You simply want to "cut" the first two characters from each line:

% find <...> | cut -b 3-
--
© 2005 Kurt Swanson AB
Keith Thompson

2006-01-17, 6:05 pm

"Xicheng" <xicheng@gmail.com> writes:
> kelly wrote:
> what you need is the basename of your files:
>
> find -name "*.c" -exec basename {} \;


Sure, but that executes the basename command for each file, which is
wasteful. It's easier and more efficient (and possibly more correct;
see below) to pipe the entire output through some filter, probably
sed:

find -name "*.c" | sed 's/^\.\///'

or, if you don't mind assuming that each line starts with "./":

find -name "*.c" | sed 's/..//'

or

find -name "*.c" | cut -c3-

The first solution is a bit more robust if you change the find command
to something that doesn't produce the output you're expecting.

Note that all of these solutions keep any directory names; for
example, "./foo/bar.c" becomes "foo/bar.c", not just "bar.c". I'm
assuming the goal is to eliminate the clutter of the leading "./"
while keeping valid path names, not just to print the basename. If
that's not your goal, adjust as needed.

If you want just the basenames, *and* you happen to have GNU find, you
can use:

find -name "*.c" -printf "%f\n"

(BTW, some versions of find require the directory name to be given
explicitly, so you need 'find . -name "*.c"'. I vaguely remember that
some might also require an explicit "-print".)

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Sven Mascheck

2006-01-18, 2:50 am

Keith Thompson wrote:

> find -name [...]
>
> (BTW, some versions of find require the directory name to be given


AFAIK all current implementations but GNU and busybox require it,
so it makes no sense to omit the path-list in this group.

> I vaguely remember that some might also require an explicit "-print".


AFAIK, no current implementation requires it. But if you use older
systems, you're likely to run into this (e.g., AIX 3, IRIX 5,
SunOS 4,...5.4, Ultrix, all SVR4-derivatives)
--
<http://www.in-ulm.de/~mascheck/various/find/>
Lew Pitcher

2006-01-18, 2:50 am

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

kelly wrote:
> find output:
> ./star.c
> ./encrypt.cl.c
> ./test.c
>
> I want the final output to be
> star.c
> encrypt.c
> test.c

[snip]

Try

find -name '*.c' -exec basename {} \;


- --
Lew Pitcher

Master Codewright & JOAT-in-training | GPG public key available on request
Registered Linux User #112576 (http://counter.li.org/)
Slackware - Because I know what I'm doing.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.7 (GNU/Linux)

iD8DBQFDzboAagVFX4UWr64RAn+ZAJ97ODgwdECv
irhML1Mwc6WuIYfS2QCdGKCg
V18zCWXORSNV6+zKinqxvqk=
=/lJd
-----END PGP SIGNATURE-----
Xicheng

2006-01-18, 2:50 am

Keith Thompson wrote:
> Sure, but that executes the basename command for each file, which is
> wasteful. It's easier and more efficient (and possibly more correct;

right..:-)

> If you want just the basenames, *and* you happen to have GNU find, you
> can use:
> find -name "*.c" -printf "%f\n"


I didnt know this before..... Is there any ways that I can get the
absolute paths of my files? Looks "find" can only return the relative
paths.

> (BTW, some versions of find require the directory name to be given
> explicitly, so you need 'find . -name "*.c"'. I vaguely remember that
> some might also require an explicit "-print".)


can also use PERL to get the basename:

find . -name "*.c" | PERL -F/ -ane 'print $F[$#F]'

Xcheng

Keith Thompson

2006-01-18, 2:50 am

"Xicheng" <xicheng@gmail.com> writes:
> Keith Thompson wrote:
> right..:-)
>
>
> I didnt know this before..... Is there any ways that I can get the
> absolute paths of my files? Looks "find" can only return the relative
> paths.


If you give it an absolute path as input, it will give you absolute
paths as output:

find `pwd` -name "*.c"

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Stephane CHAZELAS

2006-01-18, 2:50 am

2006-01-17, 17:12(-05), kelly:
> find output:
> ./star.c
> ./encrypt.cl.c
> ./test.c
>
> I want the final output to be
> star.c
> encrypt.c
> test.c
>
> when I do the cmd below, all the . gets deleted,
>
> find -name "*.c" | tr -d [./]

[...]

find .//. -name '*.c' -print | sed 's:.//./::'

If you delete "./", then you might delete a "./" that is an
actual file path.

--
Stéphane
Keith Thompson

2006-01-18, 5:55 pm

Stephane CHAZELAS <this.address@is.invalid> writes:
> 2006-01-17, 17:12(-05), kelly:
> [...]
>
> find .//. -name '*.c' -print | sed 's:.//./::'
>
> If you delete "./", then you might delete a "./" that is an
> actual file path.


Why not just anchor the match rather than messing with find's output?

find . -name '*.c' -print | sed 's:^\./::'

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Stephane CHAZELAS

2006-01-18, 5:55 pm

2006-01-18, 20:08(+00), Keith Thompson:
[...]
>
> Why not just anchor the match rather than messing with find's output?
>
> find . -name '*.c' -print | sed 's:^\./::'

[...]

There can be "\n./" in a file path as well.

--
Stéphane
William

2006-01-20, 6:03 pm

"Stephane CHAZELAS" <this.address@is.invalid> wrote in message
news:slrndstjqf.9qr.stephane.chazelas@spam.is.invalid...
> 2006-01-18, 20:08(+00), Keith Thompson:
> [...]
> [...]
>
> There can be "\n./" in a file path as well.


But 's:^\./::' will only replace the first instance, which is
the correct one. (At least using the sed versions I have.) -Wm




Keith Thompson

2006-01-20, 6:03 pm

"William" <Reply@NewsGroup.Please> writes:
> "Stephane CHAZELAS" <this.address@is.invalid> wrote in message
> news:slrndstjqf.9qr.stephane.chazelas@spam.is.invalid...
>
> But 's:^\./::' will only replace the first instance, which is
> the correct one. (At least using the sed versions I have.) -Wm


If the file path contains a newline character followed by "./", sed
will see the characters "./" at the beginning of a line, even though
it's not at the beginning of the file path.

Unix allows file names to contain any character other than '/' and
'\0'. If you want your code to be absolutely robust, you can't assume
that file names don't contain arbitrary control characters, including
newlines. (A filename *can* contain '/' or '\0' if you've managed to
corrupt the file system, but you can probably ignore that
possibility.)

On the other hand, I've never seen a newline character in a file name,
and if you created the directory tree yourself, you can probably
safely ignore that possibility as well. I certainly wouldn't worry
about it for a quick one-liner.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dan Mercer

2006-01-20, 6:03 pm


"kelly" <kelly@some.com> wrote in message news:43CD6BB7.2080603@some.com...
: find output:
: ./star.c
: ./encrypt.cl.c
: ./test.c
:
: I want the final output to be
: star.c
: encrypt.c
: test.c

If you only want files from the current directory that match
specific criteria, then just:

find * -prune yada yada

The -prune will keep you in the local directory

find does not require a single directory path as its first
argument[s]. it takes any file path, for any kind of file.
You can, for instance, give it just a single filename:

# determine if file modified in last 24 hrs
if find $file -mtime -1 | read waste
then
yada yada

Or you can specify a whole string of names, none of them directories.
Or mix and match.

Dan Mercer
:
: when I do the cmd below, all the . gets deleted,
:
: find -name "*.c" | tr -d [./]
:
: leaving me with
: starc
: encryptclc
: testc
:
: tx
:


Xicheng

2006-01-20, 8:49 pm

Keith Thompson wrote:
> If you give it an absolute path as input, it will give you absolute
> paths as output:
>
> find `pwd` -name "*.c"
>

very nice, thank you very much, Keith..
Have a great weekend,
Xicheng
> --
> Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
> San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
> We must do something. This is something. Therefore, we must do this.


William

2006-01-22, 6:10 pm

"Keith Thompson" <kst-u@mib.org> wrote in message
news:lnd5imful4.fsf@nuthaus.mib.org...
> "William" <Reply@NewsGroup.Please> writes:
>
> If the file path contains a newline character followed by "./", sed
> will see the characters "./" at the beginning of a line, even though
> it's not at the beginning of the file path.


You're right, of course, what can I say, it was a friday... -Wm


jhding@tom.com

2006-01-23, 2:55 am

I perfer the following command:
<cmd>for f in `find . -name "*.c"`; do basename $f; done</cmd>
In fact, you can do even more processing with $f if you like, such as:
<cmd>for f in `find . -name "*.c"`; do basename $f; dirname $f;
done</cmd>

Good luck!

Ed Morton

2006-01-23, 2:55 am

jhding@tom.com wrote:
> I perfer the following command:
> <cmd>for f in `find . -name "*.c"`; do basename $f; done</cmd>
> In fact, you can do even more processing with $f if you like, such as:
> <cmd>for f in `find . -name "*.c"`; do basename $f; dirname $f;
> done</cmd>
>
> Good luck!
>


Please read these:

http://cfaj.freeshell.org/google
http://home.comcast.net/~j.p.h/cus-faq-2.html#14

Regards,

Ed.
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com