walk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +37 -0
- data/Rakefile +9 -0
- data/lib/walk.rb +84 -0
- data/lib/walk/version.rb +3 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/walk_spec.rb +75 -0
- data/walk.gemspec +23 -0
- metadata +98 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 35dbff654a1f378d8ae59b0784cd69fc0917d5cf
|
4
|
+
data.tar.gz: 04ee5b5848b503b109d38f4e2ed6403e09a166e6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ffc26b6b715e2635876f4047df805daff356d0a0b4a96a2a5072d710a4d31b5c8e8d45b84cb8f3ddf163f08e9edcbd7638d3569a4ff827b3b3f8ad00a4b2a5c1
|
7
|
+
data.tar.gz: f7a01444325625ea4fd1db51dad507d63f03c652c3c3201015bdcb3cb7b0bb5250256136eabc55f2954ed79a34f398f90696c80a55479eaa7f10f19318da4790
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 samonzeweb
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Walk
|
2
|
+
|
3
|
+
Walk is a simple tool to explore a directory tree, inspired by [python os.walk][1]. For each directory (and subdirectories) it give path, files and directories.
|
4
|
+
|
5
|
+
During the exploration, it don't go down into unreadable directories, and ignore content which have disappeared.
|
6
|
+
|
7
|
+
Unlike python walk, there is no error callback (now).
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
The Walk.walk function require at least the root of the tree to explore. It can be used with a code block which is called for each directory and receiving 3 arguments : the full path of the current directory, the directories, and the files inside the current directory.
|
12
|
+
|
13
|
+
require 'walk'
|
14
|
+
|
15
|
+
Walk.walk('/') do |path, dirs, files|
|
16
|
+
puts "In #{path} there are #{dirs.length} directories and #{files.length} files"
|
17
|
+
end
|
18
|
+
|
19
|
+
Without a block, Walk.walk return an enumerator :
|
20
|
+
|
21
|
+
require 'walk'
|
22
|
+
|
23
|
+
# Directories containing a least 10 files
|
24
|
+
puts Walk.walk('/')
|
25
|
+
.select { |path,dirs,files| files.length>=10 }
|
26
|
+
.map { |path,_,_| path }
|
27
|
+
|
28
|
+
Optional (keywords) arguments are :
|
29
|
+
|
30
|
+
- topdown : when true (default) the content is returned from top to bottom during tree exploration. When topdown is false, the content is returned beginning with the bottom.
|
31
|
+
- followlinks : when false (default) it doesn't explore subdirectories which are symbolic links. When followlinks is true, it can produce an infinite loop in some cases.
|
32
|
+
|
33
|
+
## Licence
|
34
|
+
|
35
|
+
Walk is released under the MIT license. See LICENSE.txt file for details.
|
36
|
+
|
37
|
+
[1]: http://docs.python.org/3.3/library/os.html#os.walk
|
data/Rakefile
ADDED
data/lib/walk.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative "walk/version"
|
2
|
+
|
3
|
+
|
4
|
+
module Walk
|
5
|
+
|
6
|
+
|
7
|
+
CURRENT_DIR = '.'
|
8
|
+
PARENT_DIR = '..'
|
9
|
+
|
10
|
+
|
11
|
+
def self.walk(root, topdown: true, followlinks: false, &block)
|
12
|
+
|
13
|
+
if block_given?
|
14
|
+
inner_walk(root, topdown, followlinks, &block)
|
15
|
+
else
|
16
|
+
Enumerator.new do |enum|
|
17
|
+
inner_walk(root, topdown, followlinks) do |path, dirs, files|
|
18
|
+
enum << [path, dirs, files]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def self.inner_walk(root, topdown, followlinks, &block)
|
27
|
+
|
28
|
+
dirs = []
|
29
|
+
files = []
|
30
|
+
path_to_explore = []
|
31
|
+
|
32
|
+
begin
|
33
|
+
Dir.entries(root).each do |entry|
|
34
|
+
|
35
|
+
next if entry==CURRENT_DIR or entry==PARENT_DIR
|
36
|
+
|
37
|
+
fullpath = File.join(root, entry)
|
38
|
+
is_file, is_dir, go_down = inspect_entry(fullpath, followlinks)
|
39
|
+
files << entry if is_file
|
40
|
+
dirs << entry if is_dir
|
41
|
+
path_to_explore << fullpath if go_down
|
42
|
+
|
43
|
+
end
|
44
|
+
rescue Errno::ENOENT => e
|
45
|
+
# current dir disappeared since parent scan, it's not an error
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
49
|
+
yield root, dirs, files if topdown
|
50
|
+
|
51
|
+
path_to_explore.each do |fullpath|
|
52
|
+
inner_walk(fullpath, topdown, followlinks, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
yield root, dirs, files unless topdown
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
def self.inspect_entry(fullpath, followlinks)
|
61
|
+
|
62
|
+
is_file = is_dir = go_down = false
|
63
|
+
|
64
|
+
if File.file?(fullpath)
|
65
|
+
is_file = true
|
66
|
+
elsif File.directory?(fullpath)
|
67
|
+
is_dir = true
|
68
|
+
if (followlinks or not File.symlink?(fullpath)) and
|
69
|
+
File.readable?(fullpath)
|
70
|
+
go_down = true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
return is_file, is_dir, go_down
|
75
|
+
|
76
|
+
rescue Errno::ENOENT => e
|
77
|
+
return nil, nil, nil
|
78
|
+
end
|
79
|
+
|
80
|
+
private_class_method :inner_walk
|
81
|
+
private_class_method :inspect_entry
|
82
|
+
|
83
|
+
|
84
|
+
end
|
data/lib/walk/version.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.color_enabled = true
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
def create_test_tree
|
9
|
+
tmpdir = Dir.mktmpdir
|
10
|
+
FileUtils.touch File.join(tmpdir, "dummy.txt")
|
11
|
+
|
12
|
+
subdir_1 = File.join(tmpdir, 'subdir_1')
|
13
|
+
Dir.mkdir(subdir_1)
|
14
|
+
FileUtils.touch File.join(subdir_1, "dummy_1.txt")
|
15
|
+
FileUtils.touch File.join(subdir_1, "dummy_2.txt")
|
16
|
+
|
17
|
+
subdir_2 = File.join(tmpdir, 'subdir_2')
|
18
|
+
Dir.mkdir(subdir_2)
|
19
|
+
FileUtils.touch File.join(subdir_1, "dummy.txt")
|
20
|
+
|
21
|
+
tmpdir
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def remove_test_tree(path)
|
26
|
+
must_begin_with = Dir.tmpdir + File::SEPARATOR
|
27
|
+
raise "Path not in temporary directory !" unless path.index(must_begin_with) == 0
|
28
|
+
FileUtils.rm_r(path)
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def add_simlink(path)
|
33
|
+
File.symlink File.join(path, 'subdir_2'), File.join(path, 'symlink')
|
34
|
+
end
|
35
|
+
|
36
|
+
|
data/spec/walk_spec.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'walk'
|
3
|
+
|
4
|
+
describe Walk do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
@test_path = create_test_tree
|
8
|
+
end
|
9
|
+
|
10
|
+
after :each do
|
11
|
+
remove_test_tree @test_path
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should find all files in directory tree' do
|
15
|
+
files_count = 0
|
16
|
+
Walk.walk(@test_path) do |path, subdirs, files|
|
17
|
+
files_count += files.length
|
18
|
+
end
|
19
|
+
expect(files_count).to be == 4
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should find all directories in directory tree' do
|
23
|
+
dirs_count = 0
|
24
|
+
Walk.walk(@test_path) do |path, subdirs, files|
|
25
|
+
dirs_count += subdirs.length
|
26
|
+
end
|
27
|
+
expect(dirs_count).to be == 2
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should return an enumerator if no block is passed' do
|
31
|
+
expect(Walk.walk(@test_path)).to be_an(Enumerator)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should give same result with enumerator than with block style' do
|
35
|
+
files_count = Walk.walk(@test_path).map { |_,_,f| f.length}.reduce(:+)
|
36
|
+
expect(files_count).to be == 4
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should return content from top to bottom by default' do
|
40
|
+
path_order = Walk.walk(@test_path).map { |path,_,_| File.basename(path) }
|
41
|
+
expect(path_order).to be == [File.basename(@test_path), 'subdir_1', 'subdir_2']
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should return content from bottom to top if speficied' do
|
45
|
+
path_order = Walk.walk(@test_path, topdown: false).map { |path,_,_| File.basename(path) }
|
46
|
+
expect(path_order).to be == ['subdir_1', 'subdir_2', File.basename(@test_path)]
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should not explore symlink by default' do
|
50
|
+
add_simlink(@test_path)
|
51
|
+
simlink_found = Walk.walk(@test_path).detect do |path,_,_|
|
52
|
+
File.basename(path) == 'symlink'
|
53
|
+
end
|
54
|
+
expect(simlink_found).to be_nil
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should explore symlink if needed' do
|
58
|
+
add_simlink(@test_path)
|
59
|
+
simlink_found = Walk.walk(@test_path, followlinks: true).detect do |path,_,_|
|
60
|
+
File.basename(path) == 'symlink'
|
61
|
+
end
|
62
|
+
expect(simlink_found).not_to be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should ignore disapearing entries' do
|
66
|
+
expect {
|
67
|
+
Walk.walk(@test_path) do |path, subdirs, files|
|
68
|
+
if path == @test_path
|
69
|
+
remove_test_tree File.join(@test_path, 'subdir_2')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
}.not_to raise_error()
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/walk.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'walk/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "walk"
|
8
|
+
spec.version = Walk::VERSION
|
9
|
+
spec.authors = ["Samuel GAY"]
|
10
|
+
spec.email = ["sam.onzeweb@gmail.com"]
|
11
|
+
spec.summary = 'Directory tree traversal tool inspired by python os.walk'
|
12
|
+
spec.homepage = ""
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: walk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Samuel GAY
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.14'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.14'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- sam.onzeweb@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- lib/walk.rb
|
68
|
+
- lib/walk/version.rb
|
69
|
+
- spec/spec_helper.rb
|
70
|
+
- spec/walk_spec.rb
|
71
|
+
- walk.gemspec
|
72
|
+
homepage: ''
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 2.0.14
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Directory tree traversal tool inspired by python os.walk
|
96
|
+
test_files:
|
97
|
+
- spec/spec_helper.rb
|
98
|
+
- spec/walk_spec.rb
|