Never been to CodeSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

Debugging a file name with a backslash character in Bash

# create a file name containing a backslash character \
file=${HOME}/Desktop/'te:st\file'.txt
echo "${file}"
echo "${file}" | sed -n -e 'l'

echo 'This is a test case for a file name containing a backslash \ character!' > "${file}"
open -e "${file}"

set -vx

# note: avoid trailing spaces in ed commands
cat <<EOF | /bin/ed -s "${file}"
H
,g|^This|s|test case|SUCCESSFUL TEST CASE|
w
EOF

open -e "${file}"


# escape backslashes
cat <<EOF | /bin/ed -s "${file//\\/\\\\}"
H
,g|^This|s|test case|SUCCESSFUL TEST CASE|
w
EOF

open -e "${file}"


# printf "%q"
help printf | sed -E "s/(%q)/$(printf '\e[1m\\1\e[m')/"
echo "${file}"
echo "$(printf "%q" "${file}")"   # cf. help printf
echo "$(printf "%q" "${file}")" | sed -n -e 'l'

# escape file name
cat <<EOF | /bin/ed -s "$(printf "%q" "${file}")"
H
,g|^This|s|backslash|BACKSLASH|
w
EOF

open -e "${file}"


echo "${file}"
echo "${file}" | sed -n -e 'l'

file="${file//\\/\\\\}"
echo "${file}"
echo "${file}" | sed -n -e 'l'


# references
man bash 2>/dev/null | less -p 'backslash'
man bash 2>/dev/null | less -p 'Each command in a pipeline'
man bash 2>/dev/null | less -p 'Functions are executed'
help printf | sed -E "s/(%q)/$(printf '\e[1m\\1\e[m')/"
open http://en.wikipedia.org/wiki/Filename


# "Each command in a pipeline is executed as a separate process (i.e., in a subshell)."
# From: man bash

# "Functions are executed in the context of the current shell; no new process is created to 
# interpret  them (contrast this with the execution of a shell script)."
# From: man bash

# "Unix-like systems are an exception, as the only control character forbidden in file names 
# is the null character, as that's the end-of-string indicator in C. Trivially, Unix also 
# excludes the path separator / from appearing in filenames."
# From: http://en.wikipedia.org/wiki/Filename

Handling file names with initial dash character

export PATH=/usr/bin:/bin:/usr/sbin:/sbin
export IFS=$' \t\n'

mkdir -p ~/Desktop/TestDir
touch ~/Desktop/TestDir/file{1,2,3,4,5}.txt
open ~/Desktop/TestDir

cd ~/Desktop/TestDir

touch -i

touch ~/Desktop/TestDir/-i

touch -- -i
chmod 000 -i
touch -- --i.txt
chmod 000 --i.txt

rm -f -i
rm -f -i -R *

rm -f -- -i
rm -f -- --i.txt

#rm -f ./-i
#rm -f ./--i.txt

rm -f -i -R *

Sorting arrays in Bash


# get a sort command that will sort -print0 output (sort0 below)

#  requires Xcode on Mac OS X
open http://developer.apple.com/technology/Xcode.html

cd ~/Desktop

# Improved GNU sort (from textutils-1.22)
open http://attractivechaos.wordpress.com/2008/08/22/improved-gnu-sort-from-textutils-122/

curl -L -O http://www.freewebs.com/attractivechaos/sort-1.22a.tar.bz2

tar -xjf sort-1.22a.tar.bz2

cd sort-1.22a


# replace
#             int eolchar = '\n';
# with
#             int eolchar = '\0';

cat <<-'EOF' | sed -e 's/^ *//' -e 's/ *$//' | ed -s ~/Desktop/sort-1.22a/sort.c
   H
   /int eolchar = '\\n';/s/\\n/\\0/
   wq
EOF


make


alias sort0=~/Desktop/sort-1.22a/sort


ar1=('g h c' abc def 123)
ar2=('1 2 3' ABC ghc DEF)
ar3=('-x' '! & ?' $'a test\nsentence' $'another test\nsentence\n.' a64bitapp a32bitapp)

printf "%s\n" "${#ar1[@]}" "${#ar2[@]}" "${#ar3[@]}"  

printf "%s\000" "${ar1[@]}" | sort0 | tr '\0' '\n'
printf "%s\000" "${ar1[@]}" | sort0 | while read -d $'\0' item; do echo "index $[i++]:   ${item}"; done

printf "%s\000" "${ar2[@]}" | sort0 | while read -d $'\0' item; do echo "index $[i++]:   ${item}"; done

printf "%s\000" "${ar3[@]}" | sort0 | while read -d $'\0' item; do echo "index $[i++]:   ${item}"; done



# sort & uniq filename suffixes

# encode \n as \777 within the find command, then sort and finally decode \777 as \n again with the tr command
# (also an exercise in single quote usage)

man ruby | less -p 777
find . -type f -name '[^.]*.*' -exec bash -c 'basename=( "${@##*.}" ); printf "%s\n" "${basename[@]//''$'"'\n'"'''/''$'"'\777'"'''}"'  _ '{}' + | \
     sort -u | nl | tr $'\777' '\n'


# same, but using sort0

find . -type f -name '[^.]*.*' -exec bash -c 'printf "%s\000" "${@##*.}"' _ '{}' + | sort0 -u | tr '\0' '\n'

find . -type f -name '[^.]*.*' -exec bash -c 'printf "%s\000" "${@##*.}"' _ '{}' + | \
         sort0 -u | while read -d $'\0' suffix; do echo "$[i++]:   ${suffix}"; done



#----------------------------------------------------------------------------



export PATH="$(/usr/sbin/sysctl -n user.cs_path)"

export IFS=$'\n'
#export IFS=$' \t\n'

ar1=('g h c' abc def 123)
ar2=('1 2 3' ABC ghc DEF)
ar3=('-x' '! & ?' $'a test\nsentence' $'another test\nsentence\n.' a64bitapp a32bitapp)

printf "%s\n" "${#ar1[@]}" "${#ar2[@]}" "${#ar3[@]}"  


# ar3
for ((i=0; i < "${#ar3[@]}"; i++)); do echo "${ar3[$i]}"; done | sort | nl
for ((i=0; i < "${#ar3[@]}"; i++)); do echo ${ar3[$i]}; done | sort | nl
for ((i=0; i < "${#ar3[@]}"; i++)); do echo "${ar3[$i]}" | ruby -0777 -n -e 'p $_.to_s'; done | nl
for ((i=0; i < "${#ar3[@]}"; i++)); do printf -- "${ar3[$i]}\n" | ruby -0777 -n -e 'p $_.to_s'; done | nl


# sort a single array
ar3sorted=( $(for ((i=0; i < "${#ar3[@]}"; i++)); do echo ${ar3[$i]}; done | sort) )
for ((i=0; i < "${#ar3sorted[@]}"; i++)); do echo "${ar3sorted[$i]}" | ruby -0777 -n -e 'p $_.to_s'; done | nl
for ((i=0; i < "${#ar3sorted[@]}"; i++)); do printf "%s\n" "${ar3sorted[$i]}" | ruby -0777 -n -e 'p $_.to_s'; done | nl


# adding \000\n as array item delimiter
printf "%s\000\n" "${ar3[@]}"  | sed -n -e 'l'
printf "%s\000\n" "${ar3[@]}"  | ruby -n -e 'p $_.to_s'
printf "%s\000\n" "${ar3[@]}"  | ruby -0777 -n -e 'p $_.to_s'
printf "%s\000\n" "${ar3[@]}" | sed -e :a -e '$!N; s/\n/NEWLINE/g; ta' | ruby -n -e 'p $_.to_s'
printf "%s\000\n" "${ar3[@]}" | sed -e :a -e '$!N; s/\n/NEWLINE/g; ta' | tr '\000' '\n' | sed -e 's/^NEWLINE//' | ruby -n -e 'p $_.to_s'


ar3sorted=( $(printf "%s\000\n" "${ar3[@]}" | sed -e :a -e '$!N; s/\n/NEWLINE/g; ta' | tr '\000' '\n' | sed -e 's/^NEWLINE//' | sort) )
for ((i=0; i < "${#ar3sorted[@]}"; i++)); do printf -- "${ar3sorted[$i]//NEWLINE/\n}" | ruby -0777 -n -e 'p $_.to_s'; done | nl


# sort multiple arrays; convert embedded newline characters into single spaces
ar4=( $(printf "%s\n\000" "${ar1[@]}" "${ar2[@]}" "${ar3[@]}" | tr '\n' ' ' | tr '\000' '\n' | sort) )

# sort multiple arrays; preserve embedded newline characters as NEWLINE
ar4=( $(printf "%s\000\n" "${ar1[@]}" "${ar2[@]}" "${ar3[@]}" | sed -e :a -e '$!N; s/\n/NEWLINE/g; ta' | tr '\000' '\n' | sed -e 's/^NEWLINE//' | sort) )


printf "%s\n" "${#ar4[@]}"  
printf "%s\n" "${ar4[@]}" | nl  

for ((i=0; i < "${#ar4[@]}"; i++)); do echo ${ar4[$i]//NEWLINE/\\n}; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do echo -e ${ar4[$i]//NEWLINE/\\n}; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do printf -- ${ar4[$i]//NEWLINE/\\n}"\n"; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do printf -- "${ar4[$i]//NEWLINE/\n}\n"; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do printf "%s\n" ${ar4[$i]//NEWLINE/\\n}; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do printf -- "${ar4[$i]//NEWLINE/\n}\n" | ruby -0777 -n -e 'p $_.to_s'; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do printf "%s\n" "${ar4[$i]//NEWLINE/\n}" | ruby -0777 -n -e 'p $_.to_s'; done | nl