3

I have a string which looks something like this

dir/subdir/othersubdir/file.txt

But it can also look like

dir/file.txt

or

dir/subdir/file.txt

Now, I am making a script where $P is the full path to the directory were file.txt is.

Now I use this

sed 's/\/.*txt//g'

To be replace anything that ends with txt and comes after a /. This works fine when there is something like dir/file.txt, but not any of my other examples. How can I fix so that it matches what I want?

I don't want to match any subdirectories before .*txt. I want to remove only the file base name.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
DisplayName
  • 11,468
  • 20
  • 73
  • 115

4 Answers4

4

If you don't insist on using sed then you could consider using dirname:

S="dir/subdir/othersubdir/file.txt"
P=$(dirname $S)
echo $P
dir/subdir/othersubdir

S="dir/file.txt"
P=$(dirname $S)
echo $P
dir
garethTheRed
  • 33,289
  • 4
  • 92
  • 101
2

Here is sed command:

$ P="dir/subdir/othersubdir/file.txt"
$ sed -r 's/^(.*)\/.*\.txt$/\1/' <<< $P
dir/subdir/othersubdir

In above sed command we capture anything.* from beginning^ of variable P that ends$ with/*.txt, which it's known as a captured group with\1 as its beck-reference because used a pair of parentheses around it(.*), then in replacement part of sed command, we prints only captured group by using its back-reference.

αғsнιη
  • 40,939
  • 15
  • 71
  • 114
0

If you are using zsh life is much simpler, just use :h modifier:

$ var='dir/subdir/othersubdir/file.txt'
$ echo "$var:h"
dir/subdir/othersubdir
jimmij
  • 46,064
  • 19
  • 123
  • 136
0

Using Raku (formerly known as Perl_6)

~$ raku -ne 'put IO::Spec::Unix.splitpath($_).[1];'    file.txt

#OR (on Unix)

~$ raku -ne 'put .IO.dirname;'    file.txt

Raku is a programming language in the Perl-family. The first code example above takes your file paths and treats them as IO objects, of which there are four main classes (Unix, Windows, Cygwin, and QNX). Because your file consists of Unix paths, the IO::Spec::Unix method is called, to correctly understand the path delimiter, etc. (Note these separate functions allow you to, for example, manipulate Windows paths on a Unix box). Then splitpath breaks the path into three parts: Volume, Path, and File Name (index .[1] gives you the file name).

On Unix this code simplifies in the second example to put .IO.dirname;.

Sample Input:

dir/subdir/othersubdir/file.txt
dir/subdir/file.txt
dir/file.txt

Sample Output:

dir/subdir/othersubdir
dir/subdir
dir

https://docs.raku.org/type/IO/Spec/Unix
https://docs.raku.org/routine/dirname
https://raku.org

jubilatious1
  • 2,385
  • 8
  • 16