Created
February 18, 2022 08:14
-
-
Save henrjk/c0f2194ab2f92bbde059149c0243efbc to your computer and use it in GitHub Desktop.
Copy directory tree with cp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -eu | |
# this script is meant to be run on macos with gnu cp avalable via gcp (brew install coreutils) | |
# and macs own cp as cp | |
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
cd "$SCRIPT_DIR" | |
# By default cp -R of directory tree's are not idempotent, so that the second cp does not update the previous one but is copied into an existin directory. | |
# Lets first create some testdir to be copied in folder 'stuff' | |
rm -rf stuff | |
mkdir -p stuff/nm | |
touch stuff/a | |
touch stuff/.c | |
touch stuff/nm/p | |
touch stuff/nm/.c2 | |
# TODO | |
# cp -r stuff tdir/tname did no work | |
# First showcase the problem | |
init() { | |
echo "test with $1" | |
clean_expected_actual | |
rm -rf tdir && mkdir tdir # this must exist for both gcp and cp | |
} | |
clean_expected_actual() { | |
rm -rf expected && mkdir expected | |
rm -rf actual && mkdir actual | |
} | |
check_results_tdir_tname() { | |
# -- check results | |
find tdir/tname > actual/tname | |
cat << EOF > expected/tname | |
tdir/tname | |
tdir/tname/a | |
tdir/tname/.c | |
tdir/tname/nm | |
tdir/tname/nm/.c2 | |
tdir/tname/nm/p | |
EOF | |
diff expected/tname actual/tname | |
} | |
check_confused_results() { | |
# -- check results | |
find tdir/tname > actual/tname-1 | |
cat << EOF > expected/tname-1 | |
tdir/tname | |
tdir/tname/a | |
tdir/tname/stuff | |
tdir/tname/stuff/a | |
tdir/tname/stuff/.c | |
tdir/tname/stuff/nm | |
tdir/tname/stuff/nm/.c2 | |
tdir/tname/stuff/nm/p | |
tdir/tname/.c | |
tdir/tname/nm | |
tdir/tname/nm/.c2 | |
tdir/tname/nm/p | |
EOF | |
diff expected/tname-1 actual/tname-1 | |
} | |
check_results_tdir_tname_stuff() { | |
find tdir/tname > actual/tname | |
cat << EOF > expected/tname | |
tdir/tname | |
tdir/tname/stuff | |
tdir/tname/stuff/a | |
tdir/tname/stuff/.c | |
tdir/tname/stuff/nm | |
tdir/tname/stuff/nm/.c2 | |
tdir/tname/stuff/nm/p | |
EOF | |
diff expected/tname actual/tname | |
} | |
# -- 'naive' cp command | |
init "'naive' cp command" | |
cp -r stuff tdir/tname | |
check_results_tdir_tname | |
cp -r stuff tdir/tname | |
check_confused_results | |
# -- 'naive' cp command when tdir/tname exists | |
init "'naive' cp command when tdir/tname exists" | |
mkdir tdir/tname | |
cp -r stuff tdir/tname | |
check_results_tdir_tname_stuff | |
cp -r stuff tdir/tname | |
check_results_tdir_tname_stuff | |
# -- 'naive' gnu gcp command | |
init "same with gcp" | |
gcp -r stuff tdir/tname | |
check_results_tdir_tname | |
gcp -r stuff tdir/tname | |
check_confused_results | |
# -- 'naive' gnu gcp command when tdir/tname exists | |
init "'naive' gnu gcp command when tdir/tname exists" | |
mkdir tdir/tname | |
gcp -r stuff tdir/tname | |
check_results_tdir_tname_stuff | |
gcp -r stuff tdir/tname | |
check_results_tdir_tname_stuff | |
# -- gcp using --no-target-directory | |
init "gcp using --no-target-directory" | |
gcp --no-target-directory -r stuff tdir/tname | |
check_results_tdir_tname | |
gcp --no-target-directory -r stuff tdir/tname | |
check_results_tdir_tname | |
# -- gcp using --no-target-directory with explicit stuff | |
init "gcp using --no-target-directory with explicit stuff" | |
mkdir tdir/tname | |
gcp --no-target-directory -r stuff tdir/tname/stuff | |
check_results_tdir_tname_stuff | |
gcp --no-target-directory -r stuff tdir/tname/stuff | |
check_results_tdir_tname_stuff | |
# -- gcp using --target-directory | |
init "gcp using --target-directory" | |
echo "must create target directory first otherwise fails" | |
mkdir tdir/tname | |
gcp --target-directory=tdir/tname -r stuff | |
# results reflect that the stuff name is kept: | |
check_results_tdir_tname_stuff | |
gcp --target-directory=tdir/tname -r stuff | |
check_results_tdir_tname_stuff | |
# -- gcp using cmd suggested on sov | |
init "gcp using cmd suggested on sov" | |
gcp -r stuff/. tdir/tname | |
check_results_tdir_tname | |
gcp -r stuff/. tdir/tname | |
check_results_tdir_tname | |
# -- bsd cp using cmd suggested on sov | |
init "bsd cp using cmd suggested on sov" | |
cp -r stuff/. tdir/tname | |
check_results_tdir_tname | |
cp -r stuff/. tdir/tname | |
check_results_tdir_tname | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -eu | |
# this script is meant to be run on macos with gnu cp avalable via gcp (brew install coreutils) | |
# and macs own cp as cp | |
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
cd "$SCRIPT_DIR" | |
# By default cp -R of directory tree's are not idempotent, so that the second cp does not update the previous one but is copied into an existin directory. | |
# Lets first create some testdir to be copied in folder 'stuff' | |
rm -rf stuff | |
mkdir -p stuff/nm | |
touch stuff/a | |
touch stuff/.c | |
touch stuff/nm/p | |
touch stuff/nm/.c2 | |
init() { | |
echo "test with $1" | |
clean_expected_actual | |
rm -rf tdir && mkdir tdir # this must exist for both gcp and cp | |
} | |
clean_expected_actual() { | |
rm -rf expected && mkdir expected | |
rm -rf actual && mkdir actual | |
} | |
check_results_tdir_stuff() { | |
# -- check results | |
find tdir > actual/tname | |
cat << EOF > expected/tname | |
tdir | |
tdir/stuff | |
tdir/stuff/a | |
tdir/stuff/.c | |
tdir/stuff/nm | |
tdir/stuff/nm/.c2 | |
tdir/stuff/nm/p | |
EOF | |
diff expected/tname actual/tname | |
} | |
check_results_tdir() { | |
find tdir > actual/tname | |
cat << EOF > expected/tname | |
tdir | |
tdir/a | |
tdir/.c | |
tdir/nm | |
tdir/nm/.c2 | |
tdir/nm/p | |
EOF | |
diff expected/tname actual/tname | |
} | |
# -- test 'naive' cp command | |
init "'naive' cp command" | |
cp -r stuff tdir | |
check_results_tdir_stuff | |
cp -r stuff tdir | |
check_results_tdir_stuff | |
# -- same with gcp | |
init "same with gcp" | |
gcp -r stuff tdir | |
check_results_tdir_stuff | |
gcp -r stuff tdir | |
check_results_tdir_stuff | |
# -- gcp using --no-target-directory | |
init "gcp using --no-target-directory" | |
gcp --no-target-directory -r stuff tdir | |
check_results_tdir | |
gcp --no-target-directory -r stuff tdir | |
check_results_tdir | |
# -- gcp using --target-directory | |
init "gcp using --target-directory" | |
gcp --target-directory=tdir -r stuff | |
# results reflect that the stuff name is kept: | |
check_results_tdir_stuff | |
gcp --target-directory=tdir -r stuff | |
check_results_tdir_stuff | |
# -- gcp using cmd suggested on sov | |
init "gcp using cmd suggested on sov" | |
gcp -r stuff/. tdir | |
check_results_tdir | |
gcp -r stuff/. tdir | |
check_results_tdir | |
# -- bsd cp using cmd suggested on sov | |
init "bsd cp using cmd suggested on sov" | |
cp -r stuff/. tdir | |
check_results_tdir | |
cp -r stuff/. tdir | |
check_results_tdir |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The above scripts are meant to reduce confusion about how the
cp
command works when it copies directory trees.Some related links:
cp
Target directory (GNU Coreutils 9.0)cp
command in macos, but I did not find an online developer guide for the latest version. So you may want to compare toman cp