1

I have a file abc_asdfjhdsf_ckd_dfksfj_c_12345678_223344.txt. I want the output as abc_asdfjhdsf_ckd_dfksfj_c.txt.

  • Just extract—or did you want to rename it? – Wildcard Oct 18 '15 at 23:56
2

Using sed

$ echo abc_* | sed -E 's/(([^_]*_){5}).*/\1/; s/_$/.txt/'
abc_asdfjhdsf_ckd_dfksfj_c.txt

How it works:

  • s/(([^_]*_){5}).*/\1/

    This captures the beginning of the file name, up to an including the fifth _, in group 1 and deletes the rest of it.

    In more detail, sed's substitute commands have the form s/old/new/ where old is a regular expression. In our case, the regex ([^_]*_){5} matches the first five parts. We put that regex in parens, (([^_]*_){5}), so that the first five parts are saved in group 1 which we can reference as \1. .* matches everything after the first five groups. We replace all of that with just the first five groups, \1.

  • s/_$/.txt/

    This finds the last remaining _ and replaces it with .txt.

Using awk

$ echo abc_* | awk -F_ '{print $1,$2,$3,$4,$5 ".txt"}' OFS=_
abc_asdfjhdsf_ckd_dfksfj_c.txt

This uses _ as the input and output field separators. Thus, it is just a matter of printing out the first five fields followed by .txt.

Alternate approach: removing the last two parts

The above codes keep the first five parts and discard the rest. In the sample in the question, there are seven parts, none which contain a period in them. If that is always the case, then an alternate approach (hat tip: Costas) is to remove the last two parts:

$ echo abc_* | sed -E 's/(_[^_]*){2}\././'
abc_asdfjhdsf_ckd_dfksfj_c.txt
  • You can make the awk shorter, but arguably trickier, with {NF=5;print $0".txt"} or even NF=5{print $0".txt"} – dave_thompson_085 Oct 20 '15 at 8:36
1

Referring to the original question you wanted to rename the file ending:

ls abc*
abc_asdfjhdsf_ckd_dfksfj_c_12345678_223344.csv

ls abc* | cut -d_ -f1-5 | awk '{print $1".txt";}'
abc_asdfjhdsf_ckd_dfksfj_c.txt
1
for   f in ./*_*_*_*_*_?*.txt
do    [ -e "$f" ] &&
      printf %s.txt\\n "${f%"${f#*_*_*_*_*_?}"}"
done
0

Using bash parameter expansion:

for f in abc_*; do f="${f%_*}"; echo "${f%_*}.txt"; done

Output:

abc_asdfjhdsf_ckd_dfksfj_c.txt

${f%_*} is a parameter expansion pattern that will contain the value of variable f after removing everything after the last _ (including).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.