Skip to content

Commit ca2c3bb

Browse files
committed
added docker copy polyfill script
1 parent 947b051 commit ca2c3bb

File tree

1 file changed

+191
-0
lines changed

1 file changed

+191
-0
lines changed

dcp.sh

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# v1.0.0
5+
6+
# The MIT License (MIT)
7+
#
8+
# Copyright (c) 2015 Grigoriy Chudnov
9+
#
10+
# Permission is hereby granted, free of charge, to any person obtaining a copy
11+
# of this software and associated documentation files (the "Software"), to deal
12+
# in the Software without restriction, including without limitation the rights
13+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
# copies of the Software, and to permit persons to whom the Software is
15+
# furnished to do so, subject to the following conditions:
16+
#
17+
# The above copyright notice and this permission notice shall be included in all
18+
# copies or substantial portions of the Software.
19+
#
20+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26+
# SOFTWARE.
27+
28+
self=$0
29+
30+
# print an error
31+
fatal () {
32+
echo "$0:" "$@" >&2
33+
exit 1
34+
}
35+
36+
# test whether a string contains the given substring
37+
string_contain() { [ -n "$2" ] && [ -z "${2##*$1*}" ]; }
38+
39+
# test for container path
40+
is_container_path() { string_contain ':' "$1"; }
41+
42+
# make directory inside the container
43+
container_mkdir() {
44+
docker exec -i "$1" sh -c "[ -d $2 ] || mkdir -p $2"
45+
}
46+
47+
# copy host file to container
48+
container_cp() {
49+
cmd="docker exec -i $2 sh -c 'cat > $3' < $1"
50+
eval "$cmd";
51+
}
52+
53+
# transfer file or directory from the host to a container
54+
transfer_host_container() {
55+
item_base_dir=$1
56+
item_path=$2
57+
container_id=$3
58+
container_dir=$4
59+
60+
it_dir=''
61+
if [ -d "$item_path" ]; then
62+
it_dir=$item_path
63+
elif [ -f "$item_path" ]; then
64+
it_dir=$(dirname "$item_path")
65+
it_file=$(basename "$item_path")
66+
fi
67+
68+
if [ "$it_dir" ]; then
69+
dst_dir="$container_dir"${it_dir##*$item_base_dir}
70+
container_mkdir "$container_id" "$dst_dir"
71+
72+
if [ -f "$item_path" ]; then
73+
dst_path="$dst_dir/$it_file"
74+
container_cp "$item_path" "$container_id" "$dst_path"
75+
fi
76+
fi
77+
}
78+
79+
# copy CONTAINER:PATH -> HOSTPATH
80+
copy_container_host() {
81+
docker cp "$1" "$2"
82+
}
83+
84+
# copy HOSTPATH -> CONTAINER:PATH22
85+
copy_host_container() {
86+
src_path=$1
87+
dst_container=${2%%:*}
88+
dst_path=${2##*:}
89+
90+
if [ -f "$src_path" ]; then
91+
transfer_host_container $(dirname "$src_path") "$src_path" "$dst_container" "$dst_path"
92+
elif [ -d "$src_path" ]; then
93+
dst_path=$dst_path'/'$(basename "$src_path")
94+
find "$src_path" -print0 | xargs -0 bash -c '. $0 --source-only; for it; do transfer_host_container '"$src_path"' $it '"$dst_container"' '"$dst_path"'; done;' "$self"
95+
else
96+
fatal "path $src_path not found"
97+
fi
98+
}
99+
100+
# copy CONTAINER1:PATH -> CONTAINER2:PATH
101+
copy_container_container() {
102+
tmp_dir=$(mktemp -d)
103+
copy_container_host "$1" "$tmp_dir"
104+
copy_host_container "$tmp_dir"'/'$(basename "$1") "$2"
105+
rm -r "$tmp_dir"
106+
}
107+
108+
usage() {
109+
script=$(basename "$0")
110+
echo "Usage: $script [OPTIONS] SOURCE DESTINATION
111+
112+
Copies files and directories between running containers and host
113+
114+
Patterns:
115+
$script CONTAINER:PATH HOSTPATH
116+
$script HOSTPATH CONTAINER:PATH
117+
$script CONTAINER1:PATH CONTAINER2:PATH
118+
119+
Examples:
120+
* CONTAINER:PATH -> HOSTPATH
121+
$script kickass_yonath:/home/data.txt .
122+
- Copies '/home/data.txt' from 'kickass_yonath' container to the current host directory
123+
124+
* HOSTPATH -> CONTAINER:PATH
125+
$script ./test.txt kickass_yonath:/home/e1/e2
126+
- Copies 'test.txt' from the current host directory to '/home/e1/e2' in the 'kickass_yonath' container
127+
128+
$script /home/user/Downloads/test.txt kickass_yonath:/home/e1/e2
129+
- Copies 'test.txt' from the host directory to '/home/e1/e2' in the 'kickass_yonath' container
130+
131+
$script /home/user/Downloads kickass_yonath:/home/d1/d2
132+
- Copies the entire 'Downloads' directory to '/home/d1/d2' in the 'kickass_yonath' container
133+
134+
* CONTAINER1:PATH -> CONTAINER2:PATH
135+
$script kickass_yonath:/home ecstatic_colden:/
136+
- Copies the entire 'home' directory from 'kickass_yonath' to 'ecstatic_colden'
137+
138+
$script kickass_yonath:/home/data.txt ecstatic_colden:/
139+
- Copies 'data.txt' file from 'kickass_yonath' conrainer to the 'ecstatic_colden' container
140+
141+
Options:
142+
-h Display this help message
143+
"
144+
}
145+
146+
main() {
147+
# parse options
148+
while getopts ':h:' option; do
149+
case "${option}" in
150+
h) usage
151+
exit
152+
;;
153+
\?) fatal "Invalid option: -$OPTARG"
154+
exit
155+
;;
156+
esac
157+
done
158+
shift $((OPTIND - 1))
159+
160+
# check arguments
161+
if [ $# -eq 0 ]; then
162+
usage
163+
exit
164+
fi
165+
166+
# run
167+
src=$1
168+
dst=$2
169+
170+
if [ -n "$src" ] && [ -n "$dst" ]; then
171+
if is_container_path "$src"; then
172+
if is_container_path "$dst"; then
173+
copy_container_container "$src" "$dst"
174+
else
175+
copy_container_host "$src" "$dst"
176+
fi
177+
else
178+
if is_container_path "$dst"; then
179+
copy_host_container "$src" "$dst"
180+
else
181+
fatal "cannot copy files/folders from a host path to a host path"
182+
fi
183+
fi
184+
else
185+
usage
186+
fi
187+
}
188+
189+
if [ "$1" != "--source-only" ]; then
190+
main "${@}"
191+
fi

0 commit comments

Comments
 (0)