ptrack


Logs | Files | README | README | LICENSE | LICENSE | GitLab


1
commit a045a0a935b12794a6b1261c0c08b04fae8fedcc
2
Author: Connor Etherington <[email protected]>
3
Date:   Sat Jul 29 06:02:15 2023 +0200
4
5
    Update.
6
---
7
 ptrack.egg-info/PKG-INFO                    |   6 +
8
 ptrack.egg-info/SOURCES.txt                 |   9 ++
9
 ptrack.egg-info/dependency_links.txt        |   1 +
10
 ptrack.egg-info/entry_points.txt            |   4 +
11
 ptrack.egg-info/requires.txt                |   3 +
12
 ptrack.egg-info/top_level.txt               |   1 +
13
 ptrack/__init__.py                          |  14 +++
14
 ptrack/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 731 bytes
15
 ptrack/__pycache__/main.cpython-310.pyc     | Bin 0 -> 5541 bytes
16
 ptrack/main.py                              | 184 ++++++++++++++++++++++++++++
17
 setup.py                                    |  22 ++++
18
 11 files changed, 244 insertions(+)
19
20
diff --git a/ptrack.egg-info/PKG-INFO b/ptrack.egg-info/PKG-INFO
21
new file mode 100644
22
index 0000000..7da1525
23
--- /dev/null
24
+++ b/ptrack.egg-info/PKG-INFO
25
@@ -0,0 +1,6 @@
26
+Metadata-Version: 2.1
27
+Name: ptrack
28
+Version: 0.1.0
29
+Summary: A simple CLI utility for asthetically tracking progress when copying or moving files.
30
+Author: Connor Etherington
31
+Author-email: [email protected]
32
diff --git a/ptrack.egg-info/SOURCES.txt b/ptrack.egg-info/SOURCES.txt
33
new file mode 100644
34
index 0000000..f85fb63
35
--- /dev/null
36
+++ b/ptrack.egg-info/SOURCES.txt
37
@@ -0,0 +1,9 @@
38
+setup.py
39
+ptrack/__init__.py
40
+ptrack/main.py
41
+ptrack.egg-info/PKG-INFO
42
+ptrack.egg-info/SOURCES.txt
43
+ptrack.egg-info/dependency_links.txt
44
+ptrack.egg-info/entry_points.txt
45
+ptrack.egg-info/requires.txt
46
+ptrack.egg-info/top_level.txt
47
diff --git a/ptrack.egg-info/dependency_links.txt b/ptrack.egg-info/dependency_links.txt
48
new file mode 100644
49
index 0000000..8b13789
50
--- /dev/null
51
+++ b/ptrack.egg-info/dependency_links.txt
52
@@ -0,0 +1 @@
53
+
54
diff --git a/ptrack.egg-info/entry_points.txt b/ptrack.egg-info/entry_points.txt
55
new file mode 100644
56
index 0000000..32a28e4
57
--- /dev/null
58
+++ b/ptrack.egg-info/entry_points.txt
59
@@ -0,0 +1,4 @@
60
+[console_scripts]
61
+ptc = ptrack.main:copy
62
+ptm = ptrack.main:move
63
+ptrack = ptrack.main:main
64
diff --git a/ptrack.egg-info/requires.txt b/ptrack.egg-info/requires.txt
65
new file mode 100644
66
index 0000000..382c1b3
67
--- /dev/null
68
+++ b/ptrack.egg-info/requires.txt
69
@@ -0,0 +1,3 @@
70
+rich
71
+argparse
72
+argcomplete
73
diff --git a/ptrack.egg-info/top_level.txt b/ptrack.egg-info/top_level.txt
74
new file mode 100644
75
index 0000000..c003217
76
--- /dev/null
77
+++ b/ptrack.egg-info/top_level.txt
78
@@ -0,0 +1 @@
79
+ptrack
80
diff --git a/ptrack/__init__.py b/ptrack/__init__.py
81
new file mode 100644
82
index 0000000..919fce7
83
--- /dev/null
84
+++ b/ptrack/__init__.py
85
@@ -0,0 +1,14 @@
86
+import argparse
87
+import argcomplete
88
+
89
+parser = argparse.ArgumentParser(description='A simple CLI utility for asthetically tracking progress when copying or moving files.')
90
+parser.add_argument('-v', '--verbose', action='store_true', help='verbose output')
91
+parser.add_argument('-c', '--copy', action='store_true', help='copy files (You can use `ptc` instead of `ptrack -c`)')
92
+parser.add_argument('-m', '--move', action='store_true', help='move files (You can use `ptm` instead of `ptrack -m`)')
93
+
94
+argcomplete.autocomplete(parser)
95
+args, unknown = parser.parse_known_args()
96
+
97
+verbose = args.verbose
98
+copy = args.copy
99
+move = args.move
100
diff --git a/ptrack/__pycache__/__init__.cpython-310.pyc b/ptrack/__pycache__/__init__.cpython-310.pyc
101
new file mode 100644
102
index 0000000..d544d60
103
Binary files /dev/null and b/ptrack/__pycache__/__init__.cpython-310.pyc differ
104
diff --git a/ptrack/__pycache__/main.cpython-310.pyc b/ptrack/__pycache__/main.cpython-310.pyc
105
new file mode 100644
106
index 0000000..c3479bd
107
Binary files /dev/null and b/ptrack/__pycache__/main.cpython-310.pyc differ
108
diff --git a/ptrack/main.py b/ptrack/main.py
109
new file mode 100755
110
index 0000000..bddf173
111
--- /dev/null
112
+++ b/ptrack/main.py
113
@@ -0,0 +1,184 @@
114
+import os
115
+import sys
116
+from rich.progress import Progress, BarColumn, TextColumn, TimeRemainingColumn, FileSizeColumn
117
+from rich.console import Console
118
+import shutil
119
+import ptrack
120
+
121
+verbose = ptrack.verbose
122
+argCopy = ptrack.copy
123
+argMove = ptrack.move
124
+
125
+
126
+def format_file_size(file_size):
127
+    if file_size >= 1024 * 1024 * 1024:
128
+        return f"{file_size / (1024*1024*1024):.2f} GB"
129
+    elif file_size >= 1024 * 1024:
130
+        return f"{file_size / (1024*1024):.2f} MB"
131
+    elif file_size >= 1024:
132
+        return f"{file_size / 1024:.2f} kB"
133
+    else:
134
+        return f"{file_size} bytes"
135
+
136
+
137
+def regular_copy(src, dst, console, task, progress):
138
+    with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
139
+        while True:
140
+            buf = fsrc.read(1024*1024)
141
+            if not buf:
142
+                break
143
+            fdst.write(buf)
144
+            progress.update(task, advance=len(buf))
145
+            progress.refresh()
146
+
147
+
148
+def verbose_copy(src, dst, console, current, total_files):
149
+
150
+    file_size = os.path.getsize(src)
151
+
152
+    with Progress(
153
+        BarColumn(bar_width=50),
154
+        "[progress.percentage]{task.percentage:>3.0f}%",
155
+        TimeRemainingColumn(),
156
+        "[#ea2a6f][[/#ea2a6f]",
157
+        FileSizeColumn(),
158
+        "[#ea2a6f]/[/#ea2a6f]",
159
+        TextColumn(f"[bold cyan]{format_file_size(file_size)}[/bold cyan]"),
160
+        "[#ea2a6f]][/#ea2a6f]",
161
+        f"({current} of {total_files})",
162
+        console=console,
163
+        auto_refresh=False
164
+    ) as progress:
165
+        task = progress.add_task("", total=file_size, file_size=format_file_size(file_size))
166
+
167
+        with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
168
+            while not progress.finished:
169
+                buf = fsrc.read(1024*1024)
170
+                if not buf:
171
+                    break
172
+                fdst.write(buf)
173
+                progress.update(task, advance=len(buf))
174
+                progress.refresh()
175
+
176
+
177
+def run(process):
178
+    console = Console()
179
+
180
+    if len(sys.argv) < 3:
181
+        hlp()
182
+        if process == "Copying":
183
+            console.print("[bold cyan]Usage: ptc [OPTIONS] SOURCE... DESTINATION[/bold cyan]")
184
+        elif process == "Moving":
185
+            console.print("[bold cyan]Usage: ptm [OPTIONS] SOURCE... DESTINATION[/bold cyan]")
186
+        sys.exit(1)
187
+
188
+    src_paths = sys.argv[1:-1]
189
+    dst = sys.argv[-1]
190
+    srcPaths = []
191
+
192
+    for path in src_paths:
193
+        if path.endswith('/'):
194
+            path = path[:-1]
195
+        srcPaths.append(path)
196
+
197
+    if os.path.isdir(dst):
198
+        dst_dir = dst
199
+        new_name = None
200
+    else:
201
+        dst_dir = os.path.dirname(dst)
202
+        new_name = os.path.basename(dst)
203
+
204
+    total_files = sum(len(files) for path in srcPaths for r, d, files in os.walk(path) if os.path.isdir(path)) + sum(1 for path in srcPaths if os.path.isfile(path))
205
+    total_size = sum(os.path.getsize(os.path.join(r, f)) for path in srcPaths for r, d, files in os.walk(path) for f in files) + sum(os.path.getsize(path) for path in srcPaths if os.path.isfile(path))
206
+    current_file = 1
207
+
208
+    if total_files > 1:
209
+        console.print(f"\n[#ea2a6f]{process}:[/#ea2a6f] [bold cyan]{total_files} files[/bold cyan]\n")
210
+    else:
211
+        for src_path in srcPaths:
212
+            if os.path.isfile(src_path):
213
+                console.print(f"\n[#ea2a6f]{process}:[/#ea2a6f] [bold cyan] {os.path.basename(src_path)} [/bold cyan]\n")
214
+
215
+    if verbose:
216
+        for src_path in srcPaths:
217
+            if os.path.isfile(src_path):
218
+                dst_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name)
219
+                verbose_copy(src_path, dst_path, console, current_file, total_files)
220
+                current_file += 1
221
+            else:
222
+                for root, dirs, files in os.walk(src_path):
223
+                    for file in files:
224
+                        src_file_path = os.path.join(root, file)
225
+                        relative_path = os.path.relpath(src_file_path, start=src_path)
226
+                        dst_file_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name, relative_path)
227
+                        os.makedirs(os.path.dirname(dst_file_path), exist_ok=True)
228
+                        verbose_copy(src_file_path, dst_file_path, console, current_file, total_files)
229
+                        current_file += 1
230
+    else:
231
+        with Progress(
232
+            BarColumn(bar_width=50),
233
+            "[progress.percentage]{task.percentage:>3.0f}%",
234
+            TimeRemainingColumn(),
235
+            "[#ea2a6f][[/#ea2a6f]",
236
+            FileSizeColumn(),
237
+            "[#ea2a6f]/[/#ea2a6f]",
238
+            TextColumn("[bold cyan]{task.fields[total_size]}[/bold cyan]"),
239
+            "[#ea2a6f]][/#ea2a6f]",
240
+            console=console,
241
+            auto_refresh=False
242
+        ) as progress:
243
+            task = progress.add_task("", total=total_size, total_size=format_file_size(total_size))
244
+
245
+            for src_path in srcPaths:
246
+                if os.path.isfile(src_path):
247
+                    dst_file_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name)
248
+                    regular_copy(src_path, dst_file_path, console, task, progress)
249
+                else:
250
+                    for root, dirs, files in os.walk(src_path):
251
+                        for file in files:
252
+                            src_file_path = os.path.join(root, file)
253
+                            relative_path = os.path.relpath(src_file_path, start=src_path)
254
+                            dst_file_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name, relative_path)
255
+                            os.makedirs(os.path.dirname(dst_file_path), exist_ok=True)
256
+                            regular_copy(src_file_path, dst_file_path, console, task, progress)
257
+
258
+    return srcPaths
259
+
260
+
261
+def copy():
262
+    run('Copying')
263
+
264
+
265
+def move():
266
+    src_paths = run('Moving')
267
+    for src_path in src_paths:
268
+        if os.path.isfile(src_path):
269
+            os.remove(src_path)
270
+        else:
271
+            shutil.rmtree(src_path)
272
+
273
+
274
+def hlp():
275
+    print("""
276
+usage: ptrack [-h] [-v] [-c] [-m]
277
+
278
+A simple CLI utility for asthetically tracking progress when copying or moving files.
279
+
280
+options:
281
+  -h, --help     show this help message and exit
282
+  -v, --verbose  verbose output
283
+  -c, --copy     copy files (You can use `ptc` instead of `ptrack -c`)
284
+  -m, --move     move files (You can use `ptm` instead of `ptrack -m`)
285
+""")
286
+
287
+
288
+def main():
289
+    if argMove:
290
+        move()
291
+    elif argCopy:
292
+        copy()
293
+    else:
294
+        hlp()
295
+
296
+if __name__ == "__main__":
297
+    main()
298
diff --git a/setup.py b/setup.py
299
new file mode 100644
300
index 0000000..fdea560
301
--- /dev/null
302
+++ b/setup.py
303
@@ -0,0 +1,22 @@
304
+from setuptools import setup, find_packages
305
+
306
+setup(
307
+    name='ptrack',
308
+    version='0.1.0',
309
+    description='A simple CLI utility for asthetically tracking progress when copying or moving files.',
310
+    author='Connor Etherington',
311
+    author_email='[email protected]',
312
+    packages=find_packages(),
313
+    install_requires=[
314
+        'rich',
315
+        'argparse',
316
+        'argcomplete',
317
+    ],
318
+    entry_points={
319
+        'console_scripts': [
320
+            'ptc=ptrack.main:copy',
321
+            'ptm=ptrack.main:move',
322
+            'ptrack=ptrack.main:main',
323
+        ]
324
+    }
325
+)