Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make linux SPLIT command compatible with Mac OS terminal

Tags:

linux

bash

macos

I have a bash script that works fine in linux, but when I run it on my Mac terminal it fails, as the options for the splitcommand are slightly different in Mac terminal. My script is:

## Merge and half final two segments
last_file=`ls temp_filt.snplist_* | tail -n 1`
penultimate_file=`ls temp_filt.snplist_* | tail -n 2 | head -1`
cat $penultimate_file $last_file > temp && mv temp $penultimate_file
split -n l/2 $penultimate_file && mv xaa $penultimate_file; mv xab $last_file

The script fails at the final line, since the -n l/2 doesn't exist in tcsh (default shel environment in Mac OS 10.x.x). I was wondering what is the equivalent script in tcsh.

Is there a generic way to run linux script in Mac OS terminal, without the need to change the script?

like image 856
RJF Avatar asked Mar 07 '23 10:03

RJF


2 Answers

It's not the MacOS terminal that's doing the split. It's a programm called split. MacOS is built on the FreeBSD userland tools, which behave differently from the GNU utils.

There are two options:

  • Install the FreeBSD tools on your Linux boxes to make them compatible with FreeBSD.

  • Install the GNU utils on your MacOS machine. If you have brew you can do this with brew install coreutils

like image 112
datenwolf Avatar answered Mar 16 '23 06:03

datenwolf


An option is to use the language built-ins and limit external commands

Note the script contains several flaws: ls is useless and parsing ls output is not safe

array=(temp_filt.snplist_*)
last_file=${array[ -1]}
penultimate_file=${array[ -2]}

If the files are big bash read built-in will be very slow.

A simple solution in this case using cat, wc, head and tail which are compatible between systems. Note when passed in a command variables must be double quoted to avoid word splitting.

cat "$penultimate_file" "$last_file" > temp || exit 1
nb_lines=$(wc -l < temp)
((half_nb_lines=nb_lines/2))
head "-$half_nb_lines" temp > "$penultimate_file" || exit 1
tail "+$((half_nb_lines+1))" temp > "$last_file" || exit 1
rm temp

Note in the last line

command1 && command2 ; command3

the command3 is executed whatever the first exit status, { ; } may be used for grouping commands

command1 && { command2 ; command3; }
like image 28
Nahuel Fouilleul Avatar answered Mar 16 '23 06:03

Nahuel Fouilleul