--- a/FindFileApplication.st Sun Nov 12 14:21:14 2017 +0100
+++ b/FindFileApplication.st Sun Nov 12 17:55:17 2017 +0100
@@ -25,11 +25,11 @@
fileSizeUnitHolder modificationTimeOperatorHolder
modificationTimeHolder enableModificationTimeFilter
showUnreadableFilesAndDirectoriesHolder
- modificationTimeOperatorIndexHolder'
+ modificationTimeOperatorIndexHolder searchForBinaryContentsHolder'
classVariableNames:'ContentsInfoCache ContentsInfoCacheAccessLock LastRememberInCache
LastSearchIgnoredCaseInContents LastSearchIgnoredCaseInFilename
SearchStringHistory LastSearchIgnoredCaseInExcludedFilename
- LastShowUnreadableFilesAndDirectories'
+ LastShowUnreadableFilesAndDirectories LastSearchForBinaryContents'
poolDictionaries:''
category:'Interface-Tools-File'
!
@@ -113,7 +113,7 @@
^ super flyByHelpSpec addPairsFrom:#(
#contentsPattern
-'Search for files containing this. Can be matchPatterns, separated by ";"'
+'Search for files containing this. Can be matchPatterns, separated by ";".\If search for binary contents is checked, this should be a sequence of hex bytes (i.e. xx xx xx...)'
#namePattern
'Filename(s) to search for. Can be matchPatterns, separated by ";".\(eg. "*.c ; *.h" searches for C and header files. So does "*.[ch]")'
@@ -122,11 +122,14 @@
'Filename(s) to skip. Can be matchPatterns, separated by ";"'
#notContentsPattern
-'Search for files NOT containing this. Can be matchPatterns, separated by ";"'
+'Search for files NOT containing this. Can be matchPatterns, separated by ";".\If search for binary contents is checked, this should be a sequence of hex bytes (i.e. xx xx xx...)'
#searchDirectory
'Folder, where the search starts'
+#searchForBinaryContents
+'Included/Not included patterns are given as a sequence of hex bytes instead of character sequences (eg. xx xx xx...)'
+
#searchRecursive
'Recursively search in sub-folders'
@@ -143,7 +146,7 @@
'Search for files which are newer or older'
)
- "Modified: / 11-10-2017 / 15:48:53 / cg"
+ "Modified: / 12-11-2017 / 17:53:35 / cg"
! !
!FindFileApplication class methodsFor:'history'!
@@ -184,10 +187,12 @@
^
#(FullSpec
name: windowSpec
+ uuid: '79f42116-c7c7-11e7-82f7-c42c033b4871'
window:
(WindowSpec
label: 'File Search'
name: 'File Search'
+ uuid: '79f4341c-c7c7-11e7-82f7-c42c033b4871'
min: (Point 377 131)
bounds: (Rectangle 0 0 759 420)
)
@@ -197,6 +202,7 @@
(MenuPanelSpec
name: 'ToolBar1'
layout: (LayoutFrame 0 0.0 0 0 0 1.0 32 0)
+ uuid: '79f4376e-c7c7-11e7-82f7-c42c033b4871'
level: 0
menu: searchMenu
textDefault: true
@@ -204,6 +210,7 @@
(ProgressIndicatorSpec
name: 'ProgressIndicator1'
layout: (LayoutFrame 125 0 11 0 231 0 21 0)
+ uuid: '79f43a48-c7c7-11e7-82f7-c42c033b4871'
visibilityChannel: enableStop
backgroundColor: (Color 0.0 67.0 67.0)
showPercentage: false
@@ -212,6 +219,7 @@
(ViewSpec
name: 'Box1'
layout: (LayoutFrame 0 0.0 32 0 0 1.0 231 0)
+ uuid: '79f43caa-c7c7-11e7-82f7-c42c033b4871'
component:
(SpecCollection
collection: (
@@ -220,6 +228,7 @@
name: 'DirectoryLabel'
layout: (LayoutFrame 2 0 7 0 180 0 24 0)
activeHelpKey: searchDirectory
+ uuid: '79f43e3a-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
adjust: right
)
@@ -227,6 +236,7 @@
name: 'DirectoryEntryField'
layout: (LayoutFrame 180 0 4 0 -350 1 24 0)
activeHelpKey: searchDirectory
+ uuid: '79f44056-c7c7-11e7-82f7-c42c033b4871'
model: searchDirectoryHolder
immediateAccept: true
acceptOnPointerLeave: false
@@ -236,6 +246,7 @@
name: 'FileNameLabel'
layout: (LayoutFrame 2 0 31 0 180 0 48 0)
activeHelpKey: namePattern
+ uuid: '79f4433a-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
adjust: right
)
@@ -243,6 +254,7 @@
name: 'FileNameEntryField'
layout: (LayoutFrame 180 0 28 0 -350 1 48 0)
activeHelpKey: namePattern
+ uuid: '79f444b6-c7c7-11e7-82f7-c42c033b4871'
tabable: true
model: namePatternHolder
immediateAccept: true
@@ -254,6 +266,7 @@
name: 'Label1'
layout: (LayoutFrame 2 0 55 0 180 0 72 0)
activeHelpKey: excludedNamePattern
+ uuid: '79f44704-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
adjust: right
)
@@ -261,6 +274,7 @@
name: 'EntryField1'
layout: (LayoutFrame 180 0 52 0 -350 1 72 0)
activeHelpKey: excludedNamePattern
+ uuid: '79f44880-c7c7-11e7-82f7-c42c033b4871'
tabable: true
model: excludedNamePatternHolder
immediateAccept: true
@@ -272,6 +286,7 @@
name: 'ContentsLabel'
layout: (LayoutFrame 2 0 79 0 180 0 96 0)
activeHelpKey: contentsPattern
+ uuid: '79f44a88-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
adjust: right
)
@@ -279,6 +294,7 @@
name: 'ComboBox1'
layout: (LayoutFrame 180 0 76 0 -350 1 96 0)
activeHelpKey: contentsPattern
+ uuid: '79f44bfa-c7c7-11e7-82f7-c42c033b4871'
enableChannel: notSearchForSameContents
tabable: true
model: contentsPatternHolder
@@ -292,6 +308,7 @@
name: 'NotContentsLabel'
layout: (LayoutFrame 2 0 103 0 180 0 120 0)
activeHelpKey: notContentsPattern
+ uuid: '79f44ea2-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
adjust: right
)
@@ -299,6 +316,7 @@
name: 'NotContentsEntryField'
layout: (LayoutFrame 180 0 100 0 -350 1 120 0)
activeHelpKey: notContentsPattern
+ uuid: '79f4500a-c7c7-11e7-82f7-c42c033b4871'
enableChannel: notSearchForSameContents
tabable: true
model: notContentsPatternHolder
@@ -310,6 +328,7 @@
name: 'SameContentsAsLabel'
layout: (LayoutFrame 2 0 127 0 180 0 144 0)
activeHelpKey: sameContents
+ uuid: '79f45208-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
adjust: right
)
@@ -317,6 +336,7 @@
name: 'SameContentsAsEntryField'
layout: (LayoutFrame 180 0 124 0 -367 1 144 0)
activeHelpKey: sameContents
+ uuid: '79f45370-c7c7-11e7-82f7-c42c033b4871'
enableChannel: searchForSameContents
tabable: true
model: sameContentsAsHolder
@@ -327,6 +347,7 @@
name: 'EnableSameContentsCheckToggle'
layout: (LayoutOrigin -366 1 128 0)
activeHelpKey: sameContents
+ uuid: '79f45582-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
model: searchForSameContents
isTriggerOnDown: true
@@ -338,6 +359,7 @@
name: 'FileSizeLabel'
layout: (LayoutFrame 2 0 151 0 180 0 168 0)
activeHelpKey: fileSize
+ uuid: '79f458c0-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
adjust: right
)
@@ -346,6 +368,7 @@
name: 'FileSizeOperatorPopUpList'
layout: (LayoutFrame 180 0 148 0 260 0 168 0)
activeHelpKey: fileSize
+ uuid: '79f45a64-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
tabable: true
model: fileSizeOperatorHolder
@@ -361,6 +384,7 @@
name: 'FileSizeEntryField'
layout: (LayoutFrame 260 0 148 0 -367 1 168 0)
activeHelpKey: fileSize
+ uuid: '79f45cda-c7c7-11e7-82f7-c42c033b4871'
enableChannel: enableFileSizeFilterAndNotSearchForSameContents
tabable: true
model: fileSizeHolder
@@ -374,6 +398,7 @@
name: 'EnableSizeCheckToggle'
layout: (LayoutOrigin -366 1 151 0)
activeHelpKey: fileSize
+ uuid: '79f45f0a-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
model: enableFileSizeFilter
enableChannel: notSearchForSameContents
@@ -386,6 +411,7 @@
name: 'Label2'
layout: (LayoutFrame 2 0 175 0 180 0 192 0)
activeHelpKey: modificationTime
+ uuid: '79f46130-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
adjust: right
)
@@ -394,6 +420,7 @@
name: 'PopUpList1'
layout: (LayoutFrame 180 0 172 0 260 0 192 0)
activeHelpKey: modificationTime
+ uuid: '79f462b6-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
tabable: true
model: modificationTimeOperatorIndexHolder
@@ -405,6 +432,7 @@
name: 'ModifiedEntryField'
layout: (LayoutFrame 260 0 172 0 -367 1 192 0)
activeHelpKey: modificationTime
+ uuid: '79f46478-c7c7-11e7-82f7-c42c033b4871'
enableChannel: enableModificationTimeFilter
tabable: true
model: modificationTimeHolder
@@ -418,6 +446,7 @@
name: 'CheckToggle1'
layout: (LayoutOrigin -366 1 175 0)
activeHelpKey: modificationTime
+ uuid: '79f4668a-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
model: enableModificationTimeFilter
isTriggerOnDown: true
@@ -429,6 +458,7 @@
name: 'UseLocateCheckBox'
layout: (LayoutFrame -350 1 5 0 -167 1 28 0)
activeHelpKey: useLocate
+ uuid: '79f4689c-c7c7-11e7-82f7-c42c033b4871'
visibilityChannel: canUseLocate
tabable: true
model: useLocate
@@ -439,6 +469,7 @@
name: 'RecursiveSearchCheckBox'
layout: (LayoutFrame -200 1 5 0 -4 1 28 0)
activeHelpKey: recursiveSearch
+ uuid: '79f46aa4-c7c7-11e7-82f7-c42c033b4871'
tabable: true
model: searchRecursively
translateLabel: true
@@ -447,6 +478,7 @@
label: 'Directories'
name: 'SearchDirectoriesCheckBox'
layout: (LayoutFrame -350 1 29 0 -167 1 52 0)
+ uuid: '79f46c16-c7c7-11e7-82f7-c42c033b4871'
enableChannel: notSearchForSameContents
tabable: true
model: searchDirectories
@@ -457,6 +489,7 @@
name: 'IgnoreCaseInNameCheckBox'
layout: (LayoutFrame -200 1 29 0 -4 1 52 0)
activeHelpKey: ignoreCase
+ uuid: '79f46d7e-c7c7-11e7-82f7-c42c033b4871'
tabable: true
model: ignoreCaseInName
translateLabel: true
@@ -466,6 +499,7 @@
name: 'CheckBox1'
layout: (LayoutFrame -200 1 53 0 -4 1 76 0)
activeHelpKey: ignoreCase
+ uuid: '79f46edc-c7c7-11e7-82f7-c42c033b4871'
tabable: true
model: ignoreCaseInExcludedName
translateLabel: true
@@ -474,6 +508,7 @@
label: 'Use ''grep'' Cmd'
name: 'UseGrepCheckBox'
layout: (LayoutFrame -350 1 77 0 -167 1 100 0)
+ uuid: '79f4703a-c7c7-11e7-82f7-c42c033b4871'
visibilityChannel: canUseGrep
enableChannel: notSearchForSameContents
tabable: true
@@ -485,6 +520,7 @@
name: 'IgnoreCaseInContentsCheckBox'
layout: (LayoutFrame -200 1 77 0 -4 1 100 0)
activeHelpKey: ignoreCase
+ uuid: '79f47198-c7c7-11e7-82f7-c42c033b4871'
enableChannel: notSearchForSameContents
tabable: true
model: ignoreCaseInContents
@@ -495,6 +531,7 @@
name: 'IgnoreCaseInNotContentsCheckBox'
layout: (LayoutFrame -200 1 101 0 -4 1 124 0)
activeHelpKey: ignoreCase
+ uuid: '79f472f6-c7c7-11e7-82f7-c42c033b4871'
enableChannel: notSearchForSameContents
tabable: true
model: ignoreCaseInNotContents
@@ -504,26 +541,42 @@
label: 'Cache Info'
name: 'RememberInCacheCheckBox'
layout: (LayoutFrame -350 1 125 0 -167 1 148 0)
+ uuid: '79f47454-c7c7-11e7-82f7-c42c033b4871'
visibilityChannel: canUseGrep
enableChannel: searchForSameContents
tabable: true
model: rememberInCache
translateLabel: true
+ activeHelpKey: rememberInCache
)
(ActionButtonSpec
label: 'Clear Cache'
name: 'ClearCacheButton'
layout: (LayoutFrame -169 1 125 0 -21 1 147 0)
+ uuid: '79f475b2-c7c7-11e7-82f7-c42c033b4871'
translateLabel: true
model: clearCache
+ activeHelpKey: clearCache
)
(CheckBoxSpec
label: 'Show Unreadable Files and Folders'
name: 'CheckBox2'
layout: (LayoutFrame -350 1 149 0 0 1 172 0)
+ uuid: '79f477b0-c7c7-11e7-82f7-c42c033b4871'
tabable: true
model: showUnreadableFilesAndDirectoriesHolder
translateLabel: true
+ activeHelpKey: showUnreadableFilesAndDirectories
+ )
+ (CheckBoxSpec
+ label: 'Search for Binary Contents'
+ name: 'CheckBox3'
+ layout: (LayoutFrame -350 1 173 0 0 1 196 0)
+ uuid: '79f47918-c7c7-11e7-82f7-c42c033b4871'
+ tabable: true
+ model: searchForBinaryContentsHolder
+ translateLabel: true
+ activeHelpKey: searchForBinaryContents
)
)
@@ -532,6 +585,7 @@
(SequenceViewSpec
name: 'List1'
layout: (LayoutFrame 0 0.0 238 0 0 1.0 0 1)
+ uuid: '79f47abc-c7c7-11e7-82f7-c42c033b4871'
model: selectionHolder
menu: menu
hasHorizontalScrollBar: true
@@ -554,6 +608,7 @@
)
)
+ "Modified: / 12-11-2017 / 17:37:30 / cg"
! !
!FindFileApplication class methodsFor:'menu specs'!
@@ -1279,6 +1334,15 @@
^ searchDirectoryHolder.
!
+searchForBinaryContentsHolder
+ searchForBinaryContentsHolder isNil ifTrue:[
+ searchForBinaryContentsHolder := (LastSearchForBinaryContents ? false) asValue.
+ ].
+ ^ searchForBinaryContentsHolder.
+
+ "Created: / 12-11-2017 / 17:35:56 / cg"
+!
+
searchForSameContents
searchForSameContents isNil ifTrue:[
searchForSameContents := false asValue.
@@ -1468,8 +1532,11 @@
doesFileMatch contentsString notContentsString check checkNot
grepCommand nameMatch nameExcludedMatch realNameMatch
fileSizesToSearchFor filesToSearchFor fileMD5sToSearchFor
- setOfFilesToSearchFor remember cache fn dirSearchedRelative easyCheck|
+ setOfFilesToSearchFor remember cache fn dirSearchedRelative easyCheck
+ searchForBinaryContents|
+ searchForBinaryContents := self searchForBinaryContentsHolder value.
+
(aDirectoryOrCollectionOfDirectories isFilename
or:[aDirectoryOrCollectionOfDirectories isString]) ifTrue:[
theSingleDirectory := aDirectoryOrCollectionOfDirectories asFilename
@@ -1481,12 +1548,24 @@
"/ dir := aDirectory asFilename.
contentsString := contentsStringArg.
- (contentsString notEmptyOrNil and:[ ignCaseInContents ]) ifTrue:[
- contentsString := contentsString asLowercase
- ].
notContentsString := notContentsStringArg.
- (notContentsString notEmptyOrNil and:[ ignCaseInNotContents ]) ifTrue:[
- notContentsString := notContentsString asLowercase
+
+ searchForBinaryContents ifTrue:[
+ contentsString notEmptyOrNil ifTrue:[
+ contentsString := (contentsStringArg asCollectionOfWords
+ collect:[:s | Integer readFrom:s radix:16] as:ByteArray) asString.
+ ].
+ notContentsString notEmptyOrNil ifTrue:[
+ notContentsString := (notContentsStringArg asCollectionOfWords
+ collect:[:s | Integer readFrom:s radix:16] as:ByteArray) asString.
+ ].
+ ] ifFalse:[
+ (contentsString notEmptyOrNil and:[ ignCaseInContents ]) ifTrue:[
+ contentsString := contentsString asLowercase
+ ].
+ (notContentsString notEmptyOrNil and:[ ignCaseInNotContents ]) ifTrue:[
+ notContentsString := notContentsString asLowercase
+ ].
].
filenameToCompareContentsOrNil notEmptyOrNil ifTrue:[
fileSizesToSearchFor := OrderedCollection new.
@@ -1617,35 +1696,37 @@
(contentsString isEmptyOrNil and:[notContentsString isEmptyOrNil]) ifTrue:[
doesFileMatch := [:f | true].
] ifFalse:[
- (self canUseGrep and:[self useGrep value]) ifTrue:[
- (ignCaseInContents not and:[ignCaseInNotContents not]) ifTrue:[
- contentsString notEmptyOrNil ifTrue:[
- notContentsString notEmptyOrNil ifTrue:[
- grepCommand := '(grep "',contentsString,'" %1) && (grep -v "',notContentsString,'" %1)'.
+ searchForBinaryContents ifFalse:[
+ (self canUseGrep and:[self useGrep value]) ifTrue:[
+ (ignCaseInContents not and:[ignCaseInNotContents not]) ifTrue:[
+ contentsString notEmptyOrNil ifTrue:[
+ notContentsString notEmptyOrNil ifTrue:[
+ grepCommand := '(grep "',contentsString,'" %1) && (grep -v "',notContentsString,'" %1)'.
+ ] ifFalse:[
+ grepCommand := 'grep "' , contentsString , '" %1'.
+ ].
] ifFalse:[
- grepCommand := 'grep "' , contentsString , '" %1'.
+ grepCommand := 'grep -v "' , notContentsString , '" %1'.
].
- ] ifFalse:[
- grepCommand := 'grep -v "' , notContentsString , '" %1'.
- ].
- doesFileMatch := [:f | |cmd ret|
- cmd := grepCommand bindWith:f pathName.
- ret := OperatingSystem executeCommand:cmd.
- ret
- ].
- ]
+ doesFileMatch := [:f | |cmd ret|
+ cmd := grepCommand bindWith:f pathName.
+ ret := OperatingSystem executeCommand:cmd.
+ ret
+ ].
+ ]
+ ].
].
-
+
doesFileMatch isNil ifTrue:[
contentsString notEmptyOrNil ifTrue:[
- ignCaseInContents ifTrue:[
+ (searchForBinaryContents not and:[ignCaseInContents]) ifTrue:[
check := easyCheck := [:l | l includesString:contentsString caseSensitive:false]
] ifFalse:[
check := easyCheck := [:l | l includesString:contentsString]
].
].
notContentsString notEmptyOrNil ifTrue:[
- ignCaseInNotContents ifTrue:[
+ (searchForBinaryContents not and:[ignCaseInNotContents]) ifTrue:[
checkNot := [:l | (l includesString:notContentsString caseSensitive:false)]
] ifFalse:[
checkNot := [:l | (l includesString:notContentsString)]
@@ -1890,8 +1971,9 @@
contentsMatch:doesFileMatch
in:eachDir.
]
-
+
"Created: / 03-08-2011 / 18:16:02 / cg"
+ "Modified: / 12-11-2017 / 17:50:01 / cg"
!
doFindFileNamed:namePatterns directories:searchDirectories nameMatch:nameMatch contentsMatch:doesFileMatch in:aDirectory