diff --git a/configure.sh b/configure.sh index 8e0eb2d..6565626 100755 --- a/configure.sh +++ b/configure.sh @@ -4,7 +4,7 @@ folderAddress=`pwd` # 获取当前用户的根目录 userAddress=`echo $HOME` # 指定安装地址 若不存在则建立 -objectAddress="/usr/local/sbin/shell-scripts" +objectAddress="/usr/local/sbin" if [[ ! -d $objectAddress ]]; then sudo mkdir $objectAddress fi @@ -48,7 +48,7 @@ for element in ${scriptName[@]}; do objectName=${element%.*} #若链接不存在 则建立 if [[ ! -L ${objectAddress}/${objectName} ]]; then - printf "creating links for " ${objectName} "... " + printf "creating links for ${objectName} ... " sudo ln -s ${folderAddress}/${element} ${objectAddress}/${objectName} printf "done\n" fi diff --git a/gmt_shell_functions.sh b/gmt_shell_functions.sh new file mode 100755 index 0000000..be8eb3e --- /dev/null +++ b/gmt_shell_functions.sh @@ -0,0 +1,564 @@ +#!/usr/bin/env bash +# +# These functions can be used from any sh/bash script by specifying +# . gmt_shell_functions.sh +# in your script. Placing it in .bashrc makes the functions available +# on the command line as well. See documentation for usage. +# +# Note: Several of the original functions are now obsolete due to +# new functionality in GMT. These are still available for use +# but no longer documented and are placed at the end of this file +# under the OBSOLETE tag. + +#----GMT SHELL FUNCTIONS-------------------- +# Creates a unique temp directory and points GMT_TMPDIR to it +gmt_init_tmpdir () { + export GMT_TMPDIR=$(mktemp -d ${TMPDIR:-/tmp}/gmt.XXXXXX) +} + +# Remove the temp directory created by gmt_init_tmpdir +gmt_remove_tmpdir () { + rm -rf $GMT_TMPDIR + unset GMT_TMPDIR +} + +# Remove all files and directories in which the current process number is part of the file name +gmt_cleanup() { + rm -rf *$$* + if [ $# -eq 1 ]; then + rm -rf ${1}* + fi +} + +# Send a message to stderr +gmt_message() { + echo "$*" >&2 +} + +# Print a message to stderr and exit +gmt_abort() { + echo "$*" >&2 + exit +} + +# Returns the number of fields or arguments +gmt_get_nfields() { + echo $* | awk '{print NF}' +} +# Same with backwards compatible name... +gmt_nfields() { + echo $* | awk '{print NF}' +} + +# Returns the given field (arg 1) in current record (arg 2) +# Must pass arg 2 inside double quotes to preserve it as one item +gmt_get_field() { + echo $2 | cut -f$1 -d ' ' +} + +# Return w/e/s/n from given table file(s) +# May also add -Idx/dy to round off answer +gmt_get_region() { + printf "%s/%s/%s/%s\n" $(gmt info -C $* | cut -d' ' -f1-4) +} + +# Return the w/e/s/n from the header in grd file +gmt_get_gridregion() { + printf "%s/%s/%s/%s\n" $(gmt grdinfo -Cn $* | cut -d' ' -f1-4) +} + +# Make output PostScript file name based on script base name +gmt_set_psfile() { + echo $(basename $1 '.sh').ps +} + +# Make output PDF file name based on script base name +gmt_set_pdffile() { + echo $(basename $1 '.sh').pdf +} + +# For animations: Create a lexically increasing file namestem (no extension) based on prefix and frame number +# i.e., prefix_###### +gmt_set_framename() { + echo $1 $2 | awk '{printf "%s_%06d\n", $1, $2}' +} + +# For animations: Increment frame counter by one +gmt_set_framenext() { + echo $(($1 + 1)) +} + +# For KMZ: Package a bunch of *.kml [and *.png] into a single kmz +gmt_build_kmz() { + if [ $# -eq 0 ]; then + cat << EOF >&2 +gmt_build_kmz - Create a single KMZ file from many KML files + +usage: gmt_build_kmz -p [-r] *.kml [*.png] + *.kml: The KML files you want to include in the KML file. + If these link to local PNG files then list those too. + -p Specify a prefix for naming the .kmz file + -r Remove all provided files after KMZ is built [leave alone] +EOF + return + fi + if [ ! "X$1" = "X-p" ]; then + echo "gmt_build_kmz: Requires -p as first argument" >&2 + return + fi + remove=0 + name=$2 ; shift ; shift; + if [ "X$1" = "X-r" ]; then + remove=1 + shift + fi + mkdir -p kml; mv -f $* kml + cat <<- EOF > doc.kml + + + + EOF + ls kml/*.kml > /tmp/$$.lis + while read file; do + name=$(basename $file .kml) + cat << EOF >> doc.kml + + $name + + $file + + +EOF + done < /tmp/$$.lis + cat << EOF >> doc.kml + + +EOF + zip -rq9 $name.kmz doc.kml kml + if [ $remove -eq 0 ]; then + mv -f kml/* .. + fi + rm -rf kml doc.kml /tmp/$$.lis +} + +# For animations: Build animated gif from stills +gmt_build_gif() { + if [ $# -eq 0 ]; then + cat << EOF >&2 +gmt_build_gif - Process stills to animated gif with convert + +usage: gmt_build_gif [-d ] [-l ] [-r ] + is the prefix of the still images and the resulting movie + -d Specify path to of directory with the stills [current directory] + -l Specify number of times to loop, 0 for continuous [0] + -r Set frame rate in images per second [24] + -n Dry-run. Do not run convert command, just print it +EOF + return + fi + command -v ${GRAPHICSMAGICK-gm} >/dev/null 2>&1 || { echo "gmt_build_gif: Cannot find graphicsmagick in your path - exiting." >&2; return; } + rate=24; dir=.; loop=0; dryrun=0 + while [ $# -ne 1 ]; do + case "$1" in + "-d") dir=$2 ; shift ;; + "-l") loop=$2 ; shift ;; + "-n") dryrun=1 ;; + "-r") rate=$2 ; shift ;; + *) echo "gmt_build_gif: No such option ($1)" >&2 + ;; + esac + shift + done + delay=$(gmt math -Q 100 $rate DIV RINT =) # Delay to nearest 1/100 s + if [ $dryrun -eq 1 ]; then + cat <<- EOF +${GRAPHICSMAGICK-gm} convert -delay $delay -loop $loop +dither "$dir/${1}_*.*" ${1}.gif + EOF + else + ${GRAPHICSMAGICK-gm} convert -delay $delay -loop $loop +dither "$dir/${1}_*.*" ${1}.gif + echo "gmt_build_gif: GIF file is called ${1}.gif" >&2 + fi +} + +# For animations: Build a m4v movie from stills +gmt_build_movie() { + if [ $# -eq 0 ]; then + cat << EOF >&2 +gmt_build_movie - Process stills to MP4 movie with ffmpeg + Note: M4V Requires images to have an even pixel width + +usage: gmt_build_movie [-d ] [-n] [-r ] [-v] + is the prefix of the still images and the resulting movie + -d Specify path to of directory with the stills [current directory] + -r Set frame rate in images per second [24] + -n Dry-run. Do not run ffmpeg command, just print it + -v Verbose. Give progress messages +EOF + return + fi + command -v ffmpeg >/dev/null 2>&1 || { echo "gmt_build_movie: Cannot find ffmpeg in your path - exiting." >&2; return; } + rate=24; dir=.; dryrun=0; blabber=quiet + while [ $# -ne 1 ]; do + case "$1" in + "-d") dir=$2 ; shift ;; + "-n") dryrun=1 ;; + "-r") rate=$2 ; shift ;; + "-v") blabber=verbose ;; + *) echo "gmt_build_movie: No such option ($1)" >&2 + ;; + esac + shift + done + if [ $dryrun -eq 1 ]; then + cat <<- EOF +ffmpeg -loglevel $blabber -f image2 -pattern_type glob -framerate $rate -y -i "$dir/$1_*.*" -pix_fmt yuv420p ${1}.m4v + EOF + else + ffmpeg -loglevel $blabber -f image2 -pattern_type glob -framerate $rate -y -i "$dir/$1_*.*" -pix_fmt yuv420p ${1}.m4v + echo "gmt_build_movie: MP4 file is called ${1}.m4v" >&2 + fi +} + +# For animations: Build an animation script template +gmt_movie_script() { + if [ $# -eq 0 ]; then + cat << EOF >&2 +gmt_movie_script - Create template script for animation + +usage: gmt_movie_script [-c ] [-e ] [-f ] [-g ] [-h ] + [-m ] [-n ] [-r ] [-w ] + + -c Specify a standard canvas size: 360p, 480p, 720p, 1080p, or 4k + The dpi will be set automatically for a ~pagesize plot + Alternatively, specify -e -h and -w separately + -e Image resolution in dots per inch [100] + -f Video format: GIF, MP4, none [none] + -g Canvas color [white] + -h Specify image height [in inches] + -m Plot margins [1 inch] + -n Number of frames to produce [1] + -r Set frame rate per second [1] + -w Specify image width [in inches] + -u Create Web page template [no web page]. Requires -f + + is the required naming prefix of the animation products. +EOF + return + fi + all_args="$*" + dpi=100; fill=white; nframes=1; margin=1; rate=1; vformat=none; web=0; width=""; height="" + while [ $# -ne 1 ]; do + case "$1" in + "-c") canvas=$2 ; shift ;; + "-e") dpi=$2 ; shift ;; + "-g") fill=$2 ; shift ;; + "-f") vformat=$2 ; shift ;; + "-h") height=$2 ; shift ;; + "-n") nframes=$2 ; shift ;; + "-m") margin=$2 ; shift ;; + "-r") rate=$2 ; shift ;; + "-w") width=$2 ; shift ;; + "-u") web=1 ;; + *) echo "gmt_movie_script: No such option ($1)" >&2 + ;; + esac + shift + done + name=$1 + if [ "X$width" = "X" ]; then # Gave canvas, must set width, height, dpi + if [ "$canvas" = "360p" ]; then + width=4.80; height=3.60 + elif [ "$canvas" = "480p" ]; then + width=6.40; height=4.80 + elif [ "$canvas" = "720p" ]; then + width=12.80; height=7.20 + elif [ "$canvas" = "1080p" ]; then + width=9.60; height=5.40; dpi=200 + elif [ "$canvas" = "4k" ]; then + width=9.60; height=5.40; dpi=400 + fi + fi + w=$(gmt math -Q ${width} ${margin} 2 MUL SUB =) + h=$(gmt math -Q ${height} ${margin} 2 MUL SUB =) + iw=$(gmt math -Q ${width} $dpi MUL =) + ih=$(gmt math -Q ${height} $dpi MUL =) + now=$(date) + you=$(finger $LOGNAME | head -1 | awk -F': ' '{print $3}') + cat << EOF > $name.sh +#!/usr/bin/env bash +# Author: $you +# Purpose: Make an animation of ... +# Date: $now +# Command: gmt_movie_script $all_args +# +. gmt_shell_functions.sh # Load in the gmt functions +#--------------------------------------------------------------------------------- +# 1. INITIALIZATIONS: +#--------------------------------------------------------------------------------- +# 1a. Set animation parameters: +# Canvas settings: +CANVAS_WIDTH=${width} # The width of your paper canvas [in inch] +CANVAS_HEIGHT=${height} # The height of your paper canvas [in inch] +CANVAS_FILL=${fill} # The color of your paper canvas [in inch] +# Video settings: +VIDEO_DPI=$dpi # Rasterization in dots per inch [$dpi] +VIDEO_FORMAT=$vformat # Type of animation product [GIF|MP4|none] +VIDEO_FRAMES=$nframes # Number of frames in the movie +VIDEO_RATE=$rate # Frame rate (frames per sec) +VIDEO_PREFIX=$name # The prefix of the movie products +# Plot settings: +PLOT_WIDTH=${w}i # The maximum map width given your margins [in inch] +PLOT_HEIGHT=${h}i # The maximum map height given your margins [in inch] +PLOT_PDF=yes # Make a PDF of the first frame and stop [yes|no] +PLOT_XMARGIN=${margin}i # Spacing between edge and map frame on left [in inch] +PLOT_YMARGIN=${margin}i # Spacing between edge and map frame on bottom [in inch] +R=0/100/0/60 # Your data region [CHANGE THIS] +J=X\${PLOT_WIDTH}/\${PLOT_HEIGHT} # Your projection [CHANGE THIS] +#--------------------------------------------------------------------------------- +# 1b. Set the common -R -J -O -K sequence as string RJOK: +RJOK="-R\${R} -J\${J} -O -K" + +# 1c. Make a clean folder that will hold all the frame images +rm -rf \${VIDEO_PREFIX}; mkdir -p \${VIDEO_PREFIX} + +# Design your plot(s) to fit inside the canvas size. It is up to you +# to select reasonable -R -J settings so that items fit. Ultimately, the +# size of each video frame will be determined by the expression +# w x h = [\${CANVAS_WIDTH} * \$VIDEO_DPI] by [\${CANVAS_HEIGHT} * \$VIDEO_DPI] +# which currently is $iw x $ih pixels. Add your plot code between the +# FRAME PLOT BEGIN -- END lines, using overlay mode (-O -K). +# Temporary files named .\$\$\. will be deleted automatically. + +# 1d. Frame-independent assignments and calculations go here: + +# 1e. Create filled canvas as first layer in the GMT cake, then set origin. +gmt psbasemap -R0/\${CANVAS_WIDTH}/0/\${CANVAS_HEIGHT} -Jx1i -P -K -X0 -Y0 -B+n+g\${CANVAS_FILL} \\ + --PS_MEDIA=\${CANVAS_WIDTH}ix\${CANVAS_HEIGHT}i > background.\$\$.ps +gmt psxy -R -J -O -K -T -X\${PLOT_XMARGIN} -Y\${PLOT_YMARGIN} >> background.\$\$.ps + +# 1f. Add frame-independent background layers to background.\$\$.ps +# The next line is an example that can be modified or removed. +gmt psbasemap \${RJOK} -Baf -B+gpink >> background.\$\$.ps + +# 1g. Add frame-indendent foreground layers to foreground.\$\$.ps +# Place more plotting commands BEFORE next line, if needed. +gmt psxy -R -J -O -T >> foreground.\$\$.ps + +#--------------------------------------------------------------------------------- +# 2. MAIN FRAME LOOP +#--------------------------------------------------------------------------------- + +let frame=0 +while [ \$frame -lt \${VIDEO_FRAMES} ]; do + echo "Working on frame \$frame" >&2 + # 2a. Set current frame prefix for lexically increasing file name + ps=\$(gmt_set_framename \${VIDEO_PREFIX} \$frame\).ps + + # 2b. Perform any calculations that depends on the frame number + + # 2c. Start the current frame with the background layer + cp background.\$\$.ps \$ps + + # 2d. Append overlays to file \$ps; add \$RJOK to all commands + # FRAME PLOT BEGIN + # ==> Add your frame-specific plotting here + # FRAME PLOT END + + # 2e. Append the foreground layer + cat foreground.\$\$.ps >> \$ps + + if [ \$frame -eq 0 ] && [ "\${PLOT_PDF}" == "yes" ]; then + # 2f. Make a PDF of first frame only and break out + pdf=\${VIDEO_PREFIX} + gmt psconvert -Tf -P -Z -F\$pdf \$ps + echo "Made PDF of first frame: \$pdf.pdf" >&2 + echo "[Set PLOT_PDF to no to build all frames]" >&2 + break + fi + + # 2g. Convert frame to PNG and save to image folder + gmt psconvert -Tg -E\${VIDEO_DPI} -P -D\${VIDEO_PREFIX} -Z \$ps + let frame=frame+1 # Increment frame counter +done + +#--------------------------------------------------------------------------------- +# 3. CONVERT IMAGES TO AN ANIMATION FORMAT +#--------------------------------------------------------------------------------- +if [ "\${PLOT_PDF}" == "no" ]; then + if [ "\${VIDEO_FORMAT}" = "GIF" ]; then + # Make an animated GIF: + gmt_build_gif -d \${VIDEO_PREFIX} -r \${VIDEO_RATE} -l 0 \${VIDEO_PREFIX} + elif [ "\${VIDEO_FORMAT}" = "MP4" ]; then + # Make a MP4 movie: + gmt_build_movie -d \${VIDEO_PREFIX} -r \${VIDEO_RATE} \${VIDEO_PREFIX} + fi + echo "The individual frames can be found in directory \${VIDEO_PREFIX}" >&2 +fi +#--------------------------------------------------------------------------------- +# 4. REMOVE ALL TEMPORARY FILES WITH PROCESS ID IN THE NAME +#--------------------------------------------------------------------------------- +rm -f *.\$\$.* +EOF +chmod +x $name.sh +echo "gmt_movie_script: Animation script template $name.sh created" >&2 +if [ "${vformat}" = "none" ]; then + web=0 +fi +# Generate the HTML template if a graphics format was selected +if [ $web -eq 1 ]; then + cat << EOF > $name.html + +Title of the Web Page + +
+

Title of the Web Page

+EOF +if [ "${vformat}" = "GIF" ]; then + echo "" >> $name.html +else + cat << EOF >> $name.html + +EOF +fi +cat << EOF >> $name.html +
+Please add a movie caption here. +
+Created by $you on $(date) + + +EOF +echo "gmt_movie_script: Animation web template $name.html created" >&2 +fi +} + +# For spreading numerous commands across many CPUs in clusters of N lines +gmt_launch_jobs() { + # gmt_launch_jobs -c -j + # Split the non-comment records in into files + # so that number of lines per file is a multiple of . + n_cpu=$(gmt --show-cores) + if [ $# -eq 0 ]; then + cat << EOF >&2 +gmt_launch_jobs - Run chunks of commands in parallel + +usage: gmt_launch_jobs [-c ] [-l ] [-n] [-v] [-w] + is a file with a list of all the commands + -c Specify how many separate cores to use [$n_cpu] + -l Specify how many lines constitute one job cluster [1] + -n Dry-run. Do not launch jobs but leave core scripts as /tmp/gmt_launch_jobs.##.sh + -r Remove core scripts when the jobs complete + -v Verbose. Give progress messages + -w Wait for completion of all core jobs before exiting +EOF + return + fi + n_lines=1; do_wait=0; do_remove=0; dryrun=0; blabber=0 + while [ $# -ne 1 ]; do + case "$1" in + "-c") n_cpu=$2 ; shift ;; + "-l") n_lines=$2 ; shift ;; + "-n") dryrun=1 ;; + "-r") do_remove=1 ;; + "-v") blabber=1 ;; + "-w") do_wait=1 ;; + *) echo "gmt_launch_jobs: No such option ($1)" >&2 + ;; + esac + shift + done + egrep -v '^#|^$' $1 > /tmp/$$.sh + nL=$(wc -l /tmp/$$.sh | awk '{printf "%d\n", $1}') + n_chunks=$(gmt math -Q $nL $n_lines DIV =) + bad=$(gmt math -Q $n_chunks DUP RINT SUB ABS 1e-10 GT =) + if [ $bad -eq 1 ]; then + echo "gmt_launch_jobs: Your number of commands is not a multiple of $n_lines" >&2 + exit 1 + fi + if [ $n_chunks -lt $n_cpu ]; then + echo "gmt_launch_jobs: Less chunks than cores; only using $n_cpu processors" >&2 + let n_cpu=n_chunks + fi + if [ $dryrun -eq 1 ]; then + tag= + else + tag="."$$ + fi + # Create n_cpu empty files for execution + let cpu=0 + while [ $cpu -lt $n_cpu ]; do + printf "#!/usr/bin/env bash\n# gmt_launch_jobs command file chunk # ${cpu}\n#---------------------------------\n" > /tmp/gmt_launch_jobs${tag}.$cpu.sh + let cpu=cpu+1 + done + # Distribute $n_lines from the commands across these core scripts + let chunk=0; let cpu=0; let sub=n_lines-1; let last=0 + while [ $chunk -lt $n_chunks ]; do + let last=last+n_lines + let first=last-sub + sed -n ${first},${last}p /tmp/$$.sh >> /tmp/gmt_launch_jobs${tag}.$cpu.sh + let cpu=cpu+1 + if [ $cpu -eq $n_cpu ]; then + let cpu=0 + fi + let chunk=chunk+1 + done + # Launch the $n_cpu scripts + let cpu=0 + while [ $cpu -lt $n_cpu ]; do + if [ $blabber -eq 1 ]; then + echo "gmt_launch_jobs: Starting /tmp/gmt_launch_jobs${tag}.$cpu.sh" >&2 + fi + if [ $do_remove -eq 1 ]; then + echo "rm -f /tmp/gmt_launch_jobs${tag}.$cpu.sh" >> /tmp/gmt_launch_jobs${tag}.$cpu.sh + fi + if [ $dryrun -eq 0 ]; then + bash /tmp/gmt_launch_jobs${tag}.$cpu.sh & + fi + let cpu=cpu+1 + done + rm -f /tmp/$$.sh + if [ $do_wait -eq 1 ] && [ $dryrun -eq 0 ]; then + wait # Wait until all jobs launched by this script have completed + if [ $blabber -eq 1 ]; then + echo "gmt_launch_jobs: All $n_cpu jobs completed" >&2 + fi + fi +} +#=================================================================================== +# OBSOLETE: These functions are supported but obsoleted by new GMT built-in features +#=================================================================================== + +# Backwards compatible functions in use before -W was introduced in mapproject 5.2: +# Return the current map width (expects -R and -J settings) +gmt_get_map_width() { + gmt mapproject $* -Ww +} +# Same with backwards compatible name... +gmt_map_width() { + gmt mapproject $* -Ww +} + +# Return the current map height (expects -R and -J settings) +gmt_get_map_height() { + gmt mapproject $* -Wh +} +# and with backwards compatible name... +gmt_map_height() { + gmt mapproject $* -Wh +} +# Return integer total number of lines in the file(s). Obsolete since 5.4.0 +gmt_get_nrecords() { + gmt info -Fi -o4 $* +} +# Same with backwards compatible name... +gmt_nrecords() { + gmt info -Fi -o4 $* +} + +# Return integer total number of data records in the file(s). Obsolete since 5.4.0 +gmt_get_ndatarecords() { + gmt info -Fi -o2 $* +} \ No newline at end of file