Added still later: I found the problem (xlsx2csv, line 48). The 's' is specified both for infile (s='sheet'?) and separator. This line: "s|sep=s" => \ my $opt_s, should be made to be: "sep=s" => \ my $opt_s, because the s is already in use, higher up, for the infile name "i|s|in=s" => \ my $xls, (perhaps the 's' could be removed there instead) (I have not looked at the other programs, they might suffer the same ambiguity) Added later: Interesting: $ xlsx2csv --version Duplicate specification "s|sep=s" for option "s" xlsx2csv [3.9] ----- /home/aardvark/perl-5.39/bin/perl This is perl 5, version 39, subversion 6 (v5.39.6 (v5.39.5-49-gcf76a266bc)) built for x86_64-linux-thread-multi mymod = Text::CSV_XS::VERSION module = Text::CSV_XS perl = 5.39.6 Text::CSV_XS::VERSION = 1.53 ----- BUG (I think): A stray error message "Duplicate specification "s|sep=s" for option "s"" Afterward everything seems fine. Still, maybe it can be fixed. # repeat : I have no Windows or Excel so with LibreOffice (6.2) I made a simple 3-line .xlsx file with 2 data lines, 1 header line (saved in ~/tmp/test.xlsx). Then: $ inf=~/tmp/test.xlsx ; outf=~/tmp/test.csv ; xlsx2csv -U -s \\t -o "${outf}" -i "${inf}" Duplicate specification "s|sep=s" for option "s" <-- culprit Converting /home/aardvark/tmp/test.xlsx to /home/aardvark/tmp/test.csv ... 3 x 3 # yet, all seems fine: $ less ~/tmp/test.csv head1 head2 head3 A1 B1 C1 A2 B2 C2