I want to awk/sed only prefix of name of files, whenever I put a filename as a parameter to my command line.

For example,

I have multiple files:


If I execute:

sh test.sh --INFILE b.fastq.gz

My desired output would be:


Something I tried and failed was,

prefix="sed 's/.fastq//' ${INFILE}"

Using shell parameter expansion (assuming you are assigning your filename to INFILE):


Or if your suffix is sure to be fixed and you want to be more precise (always recommended when possible):




The word is expanded to produce a pattern and matched according to the rules described below (see Pattern Matching). If the pattern matches If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the value of parameter with the shortest matching pattern (the ‘%’ case) or the longest matching pattern (the ‘%%’ case) deleted. If parameter is ‘@’ or ‘’, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with ‘@’ or ‘’, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.

  • sorry for beginner question, but getting ERROR ~ unexpected token: . @ line 44, column 18. prefix="${INFILE%.fastq.gz}" ^ – Jason Jan 31 at 18:47
  • @Jason: What shell are you using? – Jesse_b Jan 31 at 18:51
  • usually bash, but the one I am currently working on is groovy. – Jason Jan 31 at 18:55
  • So your test.sh script has a hashbang that points to groovy shell? (Sorry not familiar with that one) – Jesse_b Jan 31 at 18:56
  • 2
    @Jason If you're not working in a standard Unix shell environment, then you'd better let us know about what you're doing. We were assuming you were either using the command line or writing a shell script. – Kusalananda Jan 31 at 18:57

Using the standard basename utility to remove the known suffix:

$ basename b.fastq.gz .fastq.gz

With a variable:

$ pathname="/some/path/name.fastq.gz"
$ basename "$pathname" .fastq.gz

Assigning to a variable:

$ prefix=$( basename "$pathname" .fastq.gz )
$ printf 'Prefix is "%s"\n' "$prefix"
Prefix is "name"

In a loop (over all the .fastq.gz files in the current directory):

for filename in ./*.fastq.gz; do
    prefix=$( basename "$filename" .fastq.gz )
    # Do things using "$prefix" here
  • I like this answer. However, this is assuming that you are operating using the BASH shell. While probably a pretty safe assumption, there are a few changes you would need to make if you were working in something like tcsh or straight Bourne shell. If it is Bourne (which it appears is what the poster is using to run their script in the original question), you'll probably want to use backticks "`command`" instead of the "$( command )" construct. – ParanoidGeek Jan 31 at 18:58
  • 2
    @ParanoidGeek I will not make changes to support non-POSIX shells. This would work with any current /bin/sh implementation (which all my answers do unless I specifically mention otherwise). See also Have backticks (i.e. `cmd`) in *sh shells been deprecated? – Kusalananda Jan 31 at 19:01
  • @Kusalananda - I wouldn't ask you do so. As I said, I liked your answer. – ParanoidGeek Jan 31 at 19:06

Let me fix what you tried in steps, so you can see what you were doing:

$ INFILE=b.fastq.gz; prefix="sed 's/.fastq//' ${INFILE}"; echo "$prefix"
sed 's/.fastq//' b.fastq.gz
$ INFILE=b.fastq.gz; prefix="$(sed 's/.fastq//' ${INFILE})"; echo "$prefix"
sed: can't read b.fastq.gz: No such file or directory

$ INFILE=b.fastq.gz; prefix="$(sed 's/.fastq//' <<< ${INFILE})"; echo "$prefix"
$ INFILE=b.fastq.gz; prefix="$(sed 's/\.fastq.*//' <<< ${INFILE})"; echo "$prefix"

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.