> Jose Isaias Cabrera via Cygwin writes: > > I have a new Win11 PC, and I wanted to capture the same Cygwin setup > > that I have in another Win10 PC. I copied the C:\cygwin64 folder from > > the Win10 pc to the Win11 pc,
I use the attached script (rename it to remove the .txt extension) to clone my cygwin installation. You can use the generated script to 1. perform a clean reinstall with the same set of packages as a current instance. 2. clone an existing install to another instance on this or another machine. USE AT YOUR OWN RISK. You must change the variables in the configuration section to your requirements. You can also edit the generated script, which is created in the same folder as the cygwin setup executable. HTH Doug -- Doug Henderson, Calgary, Alberta, Canada - from gmail.com
#!/usr/bin/bash -e # djh-reinstall.sh # created by Doug Henderson # inspired by similar code posted on stackoverflow and the cygwin mailing list # updated 2020-05-26 by Doug Henderson # updated 2023-11-23 by Doug Henderson # *** USE AT YOUR OWN RISK *** # djh-reinstall.sh determines a minimal set of packages which will reinstall # an existing cygwin instance. # # You can use the generated script to # 1. perform clean reinstall with the same set of packages as a current # instance. # 2. clone an existing install to another instance on this or another # machine. # # It uses the cygcheck-dep script from the cygcheck-dep package to # determine a set of packages which have no dependent packages. # It relies on cygwin setup to compute all dependencies. # You must change the variables in the configuration section to your requirements. arch=$( uname -m) if [ $arch = "x86" ] ; then bits=32 elif [ $arch = "x86_64" ] ; then bits=64 else echo "Failed to determine bits for $arch" exit 1 fi ################################ # start of configuration section # You must change the variables in this section to your requirements. # SETUP_DIR contains the Cygwin setup executable # This where you saved the installer from https://www/cygwin.com SETUP_DIR_W="D:\\Users\\Doug\\Down_Loads\\cygwin" # ROOT is the windows directory which will be the cygwin root directory. # All of cygwin is installed below this directory. # Select the 1st following line to install to same dir. # select the 2nd following line for the recommended root directory. # I recommend C:\cygwin32 and C:\cygwin64 for 32 bit and 64 bit installs. # ROOT_W="$( cygpath -wa / )" ROOT_W="C:\\cygwin${bits}" # CACHE is the windows directory containing the local package cache # You can use one directory, or one for each architecture. # It is strongly recommended that you use one for each architecture. # This folder must not be under the ROOT folder. CACHE_W="D:\\Users\\Doug\\Down_Loads\\cygwin${bits}cache" # MIRROR is the URL of a Cygwin mirror site. Pick your favourite, or fastest. # Use the same one as you select when running the installer: setup_*.exe MIRROR="http://mirrors.kernel.org/sourceware/cygwin/" # end of configuration section ############################## # remove scatch files rm -f /tmp/djh-check.* USAGE="Usage: $0 [--incomplete | -I] [--long | -L] [--overlay DIR | -O DIR] [--pause | -P] --incomplete, -I - reinstall incomplete packages only --long, -L - use setup's long instead of short form options --overlay DIR, -O DIR - use DIR as an overlay package server --pause, -P - add a pause at end of command script --verbose, -v - verbose, show some extra info --debug, -D - debug, show lots of extra info --help, -h - display usage message and exit WARNING: reinstalling incomplete python packages will downgrade those python packages that were upgraded by using 'pip install -U PKG'. " INCOMPLETE= LONG= OVERLAY= PAUSE= VERBOSE= VERSION= DEBUG= die() { echo "$*" >&2 ; exit 2 ; } # complain to STDERR and exit with error needs_arg() { if [ -z "$OPTARG" ] ; then die "No arg for --$OPT option" ; fi ; } while getopts "hvDILO:PV-:" OPT ; do # echo "*1st: OPT=$OPT OPTIND=$OPTIND NAME=$NAME OPTARG=$OPTARG" if [ "$OPT" = "-" ]; then # long option: reformulate OPT and OPTARG OPT="${OPTARG%%=*}" # extract long option name OPTARG="${OPTARG#$OPT}" # extract long option argument (may be empty) OPTARG="${OPTARG#=}" # if long option argument, remove assigning `=` # echo "*2nd: OPT=$OPT OPTIND=$OPTIND NAME=$NAME OPTARG=$OPTARG" fi case $OPT in h | help ) echo "$USAGE" ; exit 0 ;; v | verbose ) VERBOSE=true ;; D | debug ) DEBUG=true ;; I | incomplete ) INCOMPLETE=true ;; L | long ) LONG=true ;; O | overlay ) needs_arg; OVERLAY=$OPTARG ;; P | pause ) PAUSE=true ;; V | version ) VERSION=true ;; ??* ) die "Illegal option --$OPT" ;; # bad long option \?) exit 2 ;; # bad short option (error reported via getopts) *) echo "*WTF: OPT=$OPT OPTIND=$OPTIND NAME=$NAME OPTARG=$OPTARG" exit 1 ;; esac done shift $((OPTIND-1)) # remove parsed options and args from $@ list if [ -n "$DEBUG" ] ; then echo "Options: INCOMPLETE=$INCOMPLETE LONG=$LONG OVERLAY=$OVERLAY" echo " PAUSE=$PAUSE VERBOSE=$VERBOSE DEBUG=$DEBUG" echo "" fi # precompute some variables # SETUP_EXE is the architecture dependent Cygwin setup executable. SETUP_EXE="setup-$(arch).exe" # SETUP_PATH_W is the full windows path to the Cygwin setup executable. SETUP_PATH_W="${SETUP_DIR_W}\\${SETUP_EXE}" # CMD_W is the full windows path to the reinstall command we are creating. CMD_W="${SETUP_DIR_W}\\djh-reinstall${bits}.cmd" # CMD_U is the full cygwin path to the reinstall command we are creating. CMD_U="$( cygpath -u ${CMD_W} )" # show the configuration variables show_vars() { EFMT="INFO: %-14s = %-60s # %s\n" printf "${EFMT}" SETUP_DIR_W ${SETUP_DIR_W} "windows dir containing setup exe" printf "${EFMT}" ROOT_W ${ROOT_W} "windows path of cygwin root" printf "${EFMT}" CACHE_W ${CACHE_W} "setup exe cache directory" printf "${EFMT}" MIRROR ${MIRROR} "URL of preferred mirror" if true ; then echo "" printf "${EFMT}" reinstall.sh ${0} "this script" printf "${EFMT}" arch ${arch} "architecture name X86 or X86_64" printf "${EFMT}" bits ${bits} "architecture bits 32 or 64" printf "${EFMT}" SETUP_EXE ${SETUP_EXE} "setup executable name" printf "${EFMT}" SETUP_PATH_W ${SETUP_PATH_W} "windows path to setup executable" printf "${EFMT}" CMD_W ${CMD_W} "windows path to output cmd script" printf "${EFMT}" CMD_U ${CMD_U} "unix path to output cmd script" fi } if [ -n "$VERBOSE" ] || [ -n "$DEBUG" ] ; then show_vars fi # check that required programs are installed check_dep() { if [ ! -x $( which $1 > /dev/null 2>&1 ) ] ; then echo >&2 "$1 : command not found" pkg=$( cygcheck -f /usr/bin/$1 ) echo >&2 "Please install $pkg which provides $1" exit 1 fi } check_dep cygcheck-dep check_dep unix2dos.exe if [ ! -f $( cygpath -u "${SETUP_PATH_W}" ) ] ; then echo >&2 "WARNING: setup not found: $( cygpath -u ${SETUP_PATH_W} )" echo >&2 "WARNING: ${SETUP_EXE} must be installed to run the generated script" fi FMT="INFO: %-24s shows %4d packages\n" if [ -n "$INCOMPLETE" ] ; then echo "WARNING: This resets all Python packages upgraded using 'pip install -U PKG'." cygcheck -c | grep -a "Incomplete" >> /tmp/djh-check.p2.log # our sed script does: # remove everything after the first space to end of line. # delete line(s) starting with '_' (just in case). sed < /tmp/djh-check.p2.log \ -e 's/ .*$//' \ -e '/^_/d' \ > /tmp/djh-check.p2a.log p2=( $( sort --unique /tmp/djh-check.p2a.log ) ) printf "${FMT}" "cgcheck -c Incomp" ${#p2[*]} else # p1 is the list of all installed packages # p2 is the list of "leaf" packages # p3 is the list of packages recursively required by "leaf" packages echo "========================================================================" echo "(This may take a minute or so)" echo "# generated at $( date --rfc-3339=sec )" > /tmp/djh-check.p1.log cygcheck -c >> /tmp/djh-check.p1.log # our sed script does: # delete first 2 lines. # remove everything after the first space to end of line. # delete line(s) starting with '_'. sed < /tmp/djh-check.p1.log \ -e '1,2d' \ -e 's/ .*$//' \ -e '/^_/d' \ > /tmp/djh-check.p1a.log p1=( $( sort --unique /tmp/djh-check.p1a.log ) ) printf "${FMT}" "cgcheck -c" ${#p1[*]} ( echo "p1 =" ; echo " ${p1[*]}" ) > /tmp/djh-check.p1b.log echo "========================================================================" echo "(This may take a minute or so)" echo "# generated at $( date --rfc-3339=sec )" > /tmp/djh-check.dep-pp2.log ( cygcheck-dep -c -l -I 2> /dev/null || true ) >> /tmp/djh-check.dep-pp2.log # our sed script does: # delete lines starting with '/', \s+, ' _'. # remove open and closing parenthesis. # strip leading spaces. # strip trailing spaces. # replace multiple spaces with a single space. # delete empty lines. # replace spaces with newlines. sed < /tmp/djh-check.dep-pp2.log \ -e '/^\//d' \ -e '/^\#/d' \ -e '/^ _/d' \ -e '/^ ( /s/[()]//g' \ -e 's/\[Base\]//g' \ -e 's/^ *//' \ -e 's/ *$//' \ -e 's/ */ /' \ -e '/^$/d' \ -e 's/ /\n/g' \ > /tmp/djh-check.dep-pp2a.log p2=( $( sort --unique /tmp/djh-check.dep-pp2a.log ) ) printf "${FMT}" "cygcheck-dep -c -l -I" ${#p2[*]} ( echo "p2 =" ; echo " ${p2[*]}" ) > /tmp/djh-check.dep-pp2b.log echo "========================================================================" echo "(This may take a minute or so)" echo "# generated at $( date --rfc-3339=sec )" > /tmp/djh-check.dep-pp3.log ( cygcheck-dep -c -R ${p2[*]} 2> /dev/null || true ) >> /tmp/djh-check.dep-pp3.log # our sed script does: # delete lines starting with '_'. # remove 'recursively requires ' comments. # remove ')'. # strip leading spaces. # strip trailing spaces. # replace multiple spaces with a single space. # delete empty lines. # replace spaces with newlines. sed < /tmp/djh-check.dep-pp3.log \ -e '/^\#/d' \ -e '/^_/d' \ -e 's/: recursively requires ( */ /' \ -e 's/ *) *$//' \ -e 's/^ *//' \ -e 's/ *$//' \ -e '/^$/d' \ -e 's/ /\n/g' \ > /tmp/djh-check.dep-pp3a.log p3=( $( sort --unique /tmp/djh-check.dep-pp3a.log ) ) printf "${FMT}" "cygcheck-dep -c -R" ${#p3[*]} ( echo "p3 =" ; echo " ${p3[*]}" ) > /tmp/djh-check.dep-pp3b.log fi echo "========================================================================" # create the djh-reinstall command script. if [ -z $LONG ] ; then # use short options to save space opt_delete_orphans=-o opt_local_package_dir=-l opt_no_desktop=-d opt_no_shortcuts=-n opt_no_verify=-X opt_only_site=-O opt_packages=-P opt_pubkey=-K opt_quiet=-q opt_root=-R opt_site=-s opt_upgrade_also=-g else # use long options for readability opt_delete_orphans=--delete-orphans opt_local_package_dir=--local-package-dir opt_no_desktop=--no-desktop opt_no_shortcuts=--no-shortcuts opt_no_verify=--no-verify opt_only_site=--only-site opt_packages=--packages opt_pubkey=--pubkey opt_quiet=--quiet-mode opt_root=--root opt_site=--site opt_upgrade_also=--upgrade-also fi # echo "DEBUG: \$CMD_U = $CMD_U" rm -f ${CMD_U} touch ${CMD_U} cat >> ${CMD_U} <<EOF @echo off @rem This file is $CMD_W @rem It was generated @rem by ${USER}@${HOSTNAME} @rem at $( date --rfc-3339=sec ) @rem using $( cygpath -au $0 ) @rem AKA $( cygpath -aw $0 ) @rem @rem WARNING: Changes will be overwritten without warning. @rem @SETLOCAL @SETLOCAL ENABLEEXTENSIONS ${SETUP_PATH_W} ^ $opt_quiet $opt_no_desktop $opt_no_shortcuts ^ $opt_delete_orphans $opt_upgrade_also $opt_only_site ^ $opt_root "${ROOT_W}" ^ $opt_local_package_dir "${CACHE_W}" ^ $( if [ -n "$OVERLAY" ]; then echo " $opt_no_verify $opt_site $OVERLAY ^\n" ; fi; )\ $opt_site ${MIRROR} ^ $opt_packages ${p2[*]} $( if [ -n "$PAUSE" ]; then echo "@pause" ; else echo "@rem" ; fi ) EOF # sed -i -e 's/ / /g' ${CMD_U} echo "INFO: cmd line length (max=~8192): $( wc --max-line-length < ${CMD_U} )" echo "INFO: when the line length exceeds the max, you must edit \"${CMD_W}\"" echo "" # display the command script without non-echoed lines (optional) # sed < ${CMD_U} -e '/^\@/d' # Convert the command script from unix to dos line endings unix2dos -ascii --keepdate --quiet --oldfile ${CMD_U} # remove scatch files if [ -z "$DEBUG" ] ; then rm -f /tmp/djh-check.* fi # -30-
-- Problem reports: https://cygwin.com/problems.html FAQ: https://cygwin.com/faq/ Documentation: https://cygwin.com/docs.html Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple