0

I am trying to print a list of filenames to a text file, with the requirement of printing certain filenames on the same line. For example, I have 4 files.

Paleo_R1.fastq
Paleo_R2.fastq
Vegan_R1.fastq
Vegan_R2.fastq

I want the output to be

Paleo_R1.fastq Paleo_R2.fastq
Vegan_R1.fastq Vegan_R2.fastq

I know I can use the ls function and direct output to a text file, using ls >> file.txt but there are no options to print specific input line items to specific output lines.

Additionally, I am aware of that I can use for loops like this >

for file in Vegan*R1*.fastq; 
do echo $file ${file%_R1.fastq}_R2.fastq >> file.txt;
done

But I do not want to have a separate command for each filename, ie. for vegan and paleo.

Is there a way to print certain lines to specific output lines (print input lines 1 and 2 to output line 1, and input lines 3 and 4 to output line 2, and so on...)

EDIT: The rule is based on every N=2 files, not the file names.

  • Is the rule based on the file names (all files with the same first 5 characters), or every N=2 files regardless of name? – Jeff Schaller Apr 24 at 20:49
  • The rule is based on every N=2 files regardless of name. – Jamie Alfieri Apr 24 at 21:12
2

Maybe

$ ls *.fastq | xargs -n2
Bar_R1.fastq Bar_R2.fastq
Bar_R3.fastq Foo_R1.fastq
Foo_R2.fastq Foo_R3.fastq
Paleo_R1.fastq Paleo_R2.fastq
Vegan_R1.fastq Vegan_R2.fastq

or for column output

$ ls *.fastq | xargs -n2 | column -t
Bar_R1.fastq    Bar_R2.fastq
Bar_R3.fastq    Foo_R1.fastq
Foo_R2.fastq    Foo_R3.fastq
Paleo_R1.fastq  Paleo_R2.fastq
Vegan_R1.fastq  Vegan_R2.fastq

(add >> file.txt to the command to append the output to the file)

Note that both examples only work with filenames without spaces.

For files with spaces:

$ for i in *.fastq; do echo -ne "$i\0"; done | xargs -0 -n2
  • Note that redirecting this to a new file would include the name of that file in the output. – Kusalananda Apr 24 at 21:28
  • Thanks @Kusalananda, fixed by workaround. I guess it's time for bed. – Freddy Apr 24 at 21:46
0

Using the solution you already have, it's just a matter of not specifying the filename prefix Vegan:

for file in *_R1.fastq; do
    printf '%s %s\n' "$file" "${file%_R1.fastq}_R2.fastq"
done >file.txt

Using printf and redirecting after the loop instead of for each output command is just my personal preference.

For the given filenames, this generates file.txt with

Paleo_R1.fastq Paleo_R2.fastq
Vegan_R1.fastq Vegan_R2.fastq
  • Yes this would work with the data I supplied. However, this would not work if the files were not named in a consistent manner. – Jamie Alfieri Apr 24 at 21:43
  • @JamieAlfieri Do give an example of that, because there is none in the question. – Kusalananda Apr 24 at 21:57
0

One option would be to set the desired filenames as the current shell arguments and then ask printf to print them in pairs:

set -- *
printf '%s %s\n' "$@"  > output

or only certain files:

set -- *_R?.fastq

The order depends on the expansion of the wildcard that you used. If you want more control over the sequencing, then you could manually split the glob up somehow, for example:

set -- Paleo*.fastq Vegan*.fastq Omnivore*.fastq FastFood*.fastq
  • This has the benefit of grabbing the desired filenames in a separate step -- before outputting to a file that's potentially in the same directory -- so it doesn't accidentally include the filename (until the second run, of course, unless you glob around it). – Jeff Schaller Apr 25 at 1:19

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.