-
Notifications
You must be signed in to change notification settings - Fork 12
/
ntfs-fix-colon
executable file
·128 lines (105 loc) · 4 KB
/
ntfs-fix-colon
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/bin/bash
#
# progname - short desciption
#
# Copyright (C) 2012 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. See <http://www.gnu.org/licenses/gpl.html>
#
# Long description
# ... that may span over multiple lines
myname="${0##*/}"
mydir=$(dirname "$(readlink -f "$0")")
verbose=0
dirs=()
fatal() { [[ "$1" ]] && echo "$myname: error: $1" >&2 ; exit ${2:-1} ; }
message() { ((verbose)) && printf "%s\n" "$1"; }
argerr() { printf "%s: %s\n" "$myname" "${1:-error}" >&2 ; usage 1 ; }
invalid() { argerr "invalid option: $1" ; }
missing() { argerr "missing${1:+ $1} argument." ; }
skip() { i=${2:-$file}; message "skipping${i:+ $i}${1:+: $1}"; continue ; }
quit() { message "Goodbye!" ; exit; }
relpath() { python -c "import os, sys; print os.path.relpath(*sys.argv[1:3])" "$@"; }
usage() {
cat <<-USAGE
Usage: $myname [options] DIR(S)...
USAGE
if [[ "$1" ]] ; then
cat >&2 <<- USAGE
Try '$myname --help' for more information.
USAGE
exit 1
fi
cat <<-USAGE
Fix filenames cointaining colons (":"), which is an invalid character when
dealing with NTFS partitions under Windows.
Such files may be created either by Linux/NTFS-3g, which does not enforce
filename restriction, or by Windows itself when accessing networks mount
via NFS, a common scenario when sharing folders using VirtualBox.
This solves problems related to unreadable files under Windows, and delete
data supposed to be NFTS file Alternate Data Stream (ADS), such as
Thumbs.db:encryptable
Rules for deleting (or renaming) such files are:
- Files containing a colon whose prefix (the part before the last colon)
is either blank (ie, file starts with ":") or matches an existing file
are considered to be streams, and are deleted.
- Else, files are considered user-created (under Linux/NTFS-3g), and are
renamed: colons are replaced by either " -" or "-", depending if the
colon is followed by a space or not.
- If the new name already exists and is a file, content is compared. If
identical, the "stream" file is considered a duplicate and deleted.
- Otherwise, the existing name is backed up prior to rename, using
'mv --backup=numbered' rules.
Options:
-h|--help - show this page.
-v|--verbose - print more details about what is being done.
Copyright (C) 2013 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
License: GPLv3 or later. See <http://www.gnu.org/licenses/gpl.html>
USAGE
exit 0
}
# Option handling
for arg in "$@"; do [[ "$arg" == "-h" || "$arg" == "--help" ]] && usage ; done
while (( $# )); do
case "$1" in
-v|--verbose ) verbose=1 ;;
-- ) shift ; break ;;
-* ) invalid "$1" ;;
* ) dirs+=( "$1" ) ;;
esac
shift
done
dirs+=( "$@" )
[[ "$dirs" ]] || missing "DIR"
for dir in "${dirs[@]}"; do
while read -r stream; do
file="${stream%%:*}"
# Stream of a file or directory (matches a file or is blank)
if [[ -f "$stream" && ( -f "$file" || -z "$file" ) ]]; then
message "Deleting stream $stream"
rm "$stream"
continue
fi
newname=${stream//: / - }
newname=${newname//:/-}
# Check if there is duplicate file with identical content
if [[ -f "$newname" ]] && cmp --silent "$stream" "$newname"; then
message "Deleting duplicate $stream"
rm "$stream"
continue
fi
message "Renaming \"$stream\" to \"$(basename "$newname")\""
mv -T --backup=numbered "$stream" "$newname"
done < <(find "$dir" -name "*:*")
done