0

I have a file in the form of:

XXX XXXX XXX-6VwvOkZvzuI.description

How can I get just the file name XXX XXXX XXX? I've tried:

for file in $(ls .d*)
do
    fname="${file%*-}"
    ext="${filename%.*}"
done
mattb
  • 897

3 Answers3

5

Do not parse the output of ls (see e.g. Why *not* parse `ls` (and what to do instead)?). The issue that you're running into is that your loop variable, file, will take the values of your filenames after they have all been concatenated into a single long string and then split on whitespaces (and after any split-up word that happens to be a globbing pattern has been expanded). You'll get three iterations of your loop for the filename XXX XXXX XXX-6VwvOkZvzuI.description, for example, one each for the values XXX, XXXX, and XXX-6VwvOkZvzuI.description.

To iterate over all files that have a dash in their names and then a filename suffix of .description use

for name in *-*.description; do ...; done

To pick out the part before the - in $name, use a standard parameter expansion that removes everything after the first - in the string:

prefix=${name%%-*}

The difference between using %% and % here is that with %% the longest matching tail string is removed. This matters if there happens to be multiple - characters in any name.

Your loop then becomes

for name in *-*.description; do
    prefix=${name%%-*}
done

The filename suffix is already known (.description), but you can can get the bit of the filename from the - to the suffix using

infix=${name#"$prefix"}
infix=${infix%.description}

Finally, with a script like

#!/bin/sh

suffix=.description

for name in -"$suffix"; do prefix=${name%%-*} infix=${name#"$prefix"} infix=${infix%.description}

printf 'prefix="%s", infix="%s", suffix="%s"\n' \
    "$prefix" "$infix" "$suffix"

done

you'll get

$ ls
XXX XXXX XXX-6VwvOkZvzuI.description          XXX XXXX XXX-6VwvOkZvzuK.description
XXX XXXX XXX-6VwvOkZvzuJ.description          script
$ ./script
prefix="XXX XXXX XXX", infix="-6VwvOkZvzuI", suffix=".description"
prefix="XXX XXXX XXX", infix="-6VwvOkZvzuJ", suffix=".description"
prefix="XXX XXXX XXX", infix="-6VwvOkZvzuK", suffix=".description"
Kusalananda
  • 333,661
0

Edit

I'll leave my answer up, but add the warning from @Kusalananda's answer: Do not parse the output of ls (see e.g. Why *not* parse `ls` (and what to do instead)?).

My answer

You could pipe the output of ls directly into sed and substitute just the part coming before the hyphen (-):

ls *.d* | sed 's/\(.*\)-.*/\1/'

I tried this with two files called:

XXX XXXX XXX-6VwvOkZvzuI (copy).description
XXX XXXX XYZ-6VwvOkZvzuI.description

and the output is:

XXX XXXX XXX
XXX XXXX XYZ

The way the sed command is working is as follows:

  • I remember the stuff in between the above using \( and \) which in this case is everything up to the last hyphen in the file name (you'd need to adapt it if your files have later hyphens in the names)
  • Then replace with the remembered content \1 - i.e. just the XXX part

You can put the output of the command into a file if needed with:

ls *.d* | sed 's/\(.*\)-.*/\1/' > new_file
mattb
  • 897
  • Thnx I'll try it now – Dark_Stoner Jun 20 '21 at 09:22
  • if I need everything but the extension would sed be one solution? – Dark_Stoner Jun 20 '21 at 09:49
  • It all depends on how the files are named - if there is only a single dot before the extension (as in your examples in the OP), you could do ls *.d* | sed 's/\(.*\)\..*/\1/', but if you have files like filename.my.ext that method would return filename.my – mattb Jun 20 '21 at 09:52
  • @Dark_Stoner I think the answer by Kusalananda is better than mine so you should probably go with that approach – mattb Jun 20 '21 at 10:04
  • This worked for my situation the file structure will never change.fname=$(ls .d | sed -e 's/.[^.]*$//') – Dark_Stoner Jun 20 '21 at 11:37
  • @Dark_Stoner awesome, I'm glad you could tweak my approach to your situation maybe you could upvote/accept my answer or one of the others (See https://stackoverflow.com/help/someone-answers) – mattb Jun 20 '21 at 11:40
0

Try this

$ ls -1
x.sh
XXX XXXX XXX-6VwvOkZvzuI.description
YYY XXXX XXX-6VwvOkZvzuI.description
$ cat x.sh
#!/bin/bash
for file in *.d*
do
 fname=${file/-*/}
 ext=${file/*-/}
 echo fname $fname ext $ext
done
$ ./x.sh
fname XXX XXXX XXX ext 6VwvOkZvzuI.description
fname YYY XXXX XXX ext 6VwvOkZvzuI.description
$
steve
  • 21,892