Class: ShellHelpers::PathnameExt::Base

Inherits:
Pathname
  • Object
show all
Defined in:
lib/shell_helpers/pathname.rb

Direct Known Subclasses

ShellHelpers::Pathname

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Pathname

#write

Class Method Details

./(path) ⇒ Object

Pathname / 'usr'



74
75
76
# File 'lib/shell_helpers/pathname.rb', line 74

def /(path)
	new(path)
end

.[](path) ⇒ Object

Pathname['/usr']



78
79
80
# File 'lib/shell_helpers/pathname.rb', line 78

def [](path)
	new(path)
end

.cd(dir, &b) ⇒ Object



82
83
84
# File 'lib/shell_helpers/pathname.rb', line 82

def cd(dir,&b)
	self.new(dir).cd(&b)
end

.currentObject

differ from Pathname.pwd in that this returns a relative path



66
67
68
# File 'lib/shell_helpers/pathname.rb', line 66

def current
	return Pathname.new(".")
end

.homeObject



56
57
58
# File 'lib/shell_helpers/pathname.rb', line 56

def home
	return Pathname.new(Dir.home)
end

.hometildeObject



59
60
61
# File 'lib/shell_helpers/pathname.rb', line 59

def hometilde
	return Pathname.new('~')
end

.nullObject



69
70
71
# File 'lib/shell_helpers/pathname.rb', line 69

def null
	return Pathname.new('/dev/null')
end

.slashObject



62
63
64
# File 'lib/shell_helpers/pathname.rb', line 62

def slash
	return Pathname.new("/")
end

Instance Method Details

#abs_path(base: self.class.pwd, mode: :clean) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/shell_helpers/pathname.rb', line 205

def abs_path(base: self.class.pwd, mode: :clean)
	f= absolute? ? self : base+self
	case mode
	when :clean
		f.cleanpath
	when :clean_sym
		f.cleanpath(consider_symlink: true)
	when :real
		f.realpath
	when :realdir
		f.realdirpath
	else
		f
	end
end

#append_name(*args, join: '') ⇒ Object

Pathname.new("foo")+"bar" return "foo/bar" Pathname.new("foo").append_name("bar") return "foobar"



147
148
149
# File 'lib/shell_helpers/pathname.rb', line 147

def append_name(*args,join:'')
	Pathname.new(self.to_s+args.join(join))
end

#backup(suffix: '.old', overwrite: true) ⇒ Object



196
197
198
199
200
201
202
203
# File 'lib/shell_helpers/pathname.rb', line 196

def backup(suffix: '.old', overwrite: true)
	if self.exist?
		filebk=self.append_name(suffix)
		filebk=nonexisting_name if filebk.exist? and !overwrite
		logger.debug "Backup #{self} -> #{filebk}" if respond_to?(:logger)
		FileUtils.mv(self,filebk)
	end
end

#bad_symlink?Boolean

Returns:

  • (Boolean)


314
315
316
# File 'lib/shell_helpers/pathname.rb', line 314

def bad_symlink?
	symlink? and !dereference.exist?
end

#binary?Boolean

Returns:

  • (Boolean)


167
168
169
170
171
172
173
174
175
# File 'lib/shell_helpers/pathname.rb', line 167

def binary?
	return false if directory?
	bytes = stat.blksize
	bytes = 4096 if bytes > 4096
	s = read(bytes, bytes) || ""
	#s = s.encode('US-ASCII', :undef => :replace).split(//)
	s=s.split(//)
	((s.size - s.grep(" ".."~").size) / s.size.to_f) > 0.30
end

#call(prog, *args, pos: :last, full: false, **opts) ⇒ Object

calls an external program



357
358
359
360
361
362
363
364
# File 'lib/shell_helpers/pathname.rb', line 357

def call(prog,*args,pos: :last,full:false,**opts)
	name=to_s
	name=(self.class.pwd+self).to_s if full and relative?
	sh_args=args
	pos=sh_args.length if pos==:last
	sh_args[pos,0]=name
	Sh.sh(prog,*sh_args,**opts)
end

#chattr(*args, **opts) ⇒ Object



366
367
368
# File 'lib/shell_helpers/pathname.rb', line 366

def chattr(*args,**opts)
	call("chattr",*args,**opts)
end

#componentsObject



129
130
131
# File 'lib/shell_helpers/pathname.rb', line 129

def components
	each_filename.to_a
end

#convert_path(base: self.class.pwd, mode: :clean, checkdir: false) ⇒ Object

call abs_path or rel_path according to :mode



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/shell_helpers/pathname.rb', line 230

def convert_path(base: self.class.pwd, mode: :clean, checkdir: false)
	case mode
	when :clean
		cleanpath
	when :clean_sym
		cleanpath(consider_symlink: true)
	when :rel
		rel_path(base: base, checkdir: checkdir)
	when :relative
		rel_path(base: base, checkdir: checkdir) unless self.relative?
	when :absolute,:abs
		abs_path(base: base, mode: :abs)
	when :abs_clean
		abs_path(base: base, mode: :clean)
	when :abs_cleansym
		abs_path(base: base, mode: :cleansym)
	when :abs_real
		abs_path(base: base, mode: :real)
	when :abs_realdir
		abs_path(base: base, mode: :realdir)
	else
		self
	end
end

#copy_entry(dest, dereference: false, preserve: true) ⇒ Object

use the low level FileUtils feature to copy the metadata if passed a dir just copy the dir metadata, not the directory recursively Note this differs from FileUtils.copy_entry who copy directories recursively



48
49
50
51
52
53
# File 'lib/shell_helpers/pathname.rb', line 48

def copy_entry(dest, dereference: false, preserve: true)
	require 'fileutils'
	ent = FileUtils::Entry_.new(@path, nil, dereference)
	ent.copy dest.to_s
	ent. dest.to_s if preserve
end

#depthObject



132
133
134
# File 'lib/shell_helpers/pathname.rb', line 132

def depth
	each_filename.count
end

#dereference(mode = true) ⇒ Object



303
304
305
306
307
308
309
310
311
312
# File 'lib/shell_helpers/pathname.rb', line 303

def dereference(mode=true)
	return self unless mode
	case mode
	when :simple
		return follow if symlink?
	else
		return follow.dereference(mode) if symlink?
	end
	self
end

#entries(filter: true) ⇒ Object



136
137
138
139
140
141
142
143
# File 'lib/shell_helpers/pathname.rb', line 136

def entries(filter: true)
	c=super()
	if filter
		c.reject {|c| c.to_s=="." or c.to_s==".."}
	else
		c
	end
end

#filewrite(*args, mode: "w", perm: nil, mkpath: false, backup: false) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/shell_helpers/pathname.rb', line 109

def filewrite(*args,mode:"w",perm: nil,mkpath: false,backup: false)
	logger.debug("Write to #{self}"+ (perm ? " (#{perm})" : "")) if respond_to?(:logger)
	self.dirname.mkpath if mkpath
	self.backup if backup and exist?
	if !exist? && symlink?
		logger.debug "Removing bad symlink #{self}" if respond_to?(:logger)
		self.unlink
	end
	self.open(mode: mode) do |fh|
		fh.chmod(perm) if perm
		#hack to pass an array to write and do the right thing
		if args.length == 1 && Array === args.first
			fh.puts(args.first)
		else
			fh.write(*args)
		end
		yield fh if block_given?
	end
end

#find(*args, &b) ⇒ Object



276
277
278
279
# File 'lib/shell_helpers/pathname.rb', line 276

def find(*args,&b)
	require 'shell_helpers/utils'
	Utils.find(self,*args,&b)
end

#followObject

follow a symlink



293
294
295
296
297
298
299
300
301
# File 'lib/shell_helpers/pathname.rb', line 293

def follow
	return self unless symlink?
	l=readlink
	if l.relative?
		self.dirname+l
	else
		l
	end
end

#hidden?Boolean

Returns:

  • (Boolean)


318
319
320
321
# File 'lib/shell_helpers/pathname.rb', line 318

def hidden?
	#without abs_path '.' is considered as hidden
	abs_path.basename.to_s[0]=="."
end

#may_exist?Boolean

exist? returns false if called on a symlink pointing to a non existing file

Returns:

  • (Boolean)


97
98
99
# File 'lib/shell_helpers/pathname.rb', line 97

def may_exist?
	exist? or symlink?
end

#new_name(cond) ⇒ Object

loop until we get a name satisfying cond



152
153
154
155
156
157
# File 'lib/shell_helpers/pathname.rb', line 152

def new_name(cond)
	loop.with_index do |_,ind|
		n=self.class.new(yield(self,ind))
		return n if cond.call(n)
	end
end

#nonexisting_nameObject

find a non existing filename



159
160
161
162
163
164
# File 'lib/shell_helpers/pathname.rb', line 159

def nonexisting_name
	return self unless self.may_exist?
	new_name(Proc.new {|f| !f.may_exist?}) do |old_name, ind|
		old_name.append_name("%02d" % ind)
	end
end

#orig_findObject

overwrites Pathname#find



275
# File 'lib/shell_helpers/pathname.rb', line 275

alias orig_find find

#read!Object

like read, but output nil rather than an exception if the file does not exist



103
104
105
106
107
# File 'lib/shell_helpers/pathname.rb', line 103

def read!
		read
rescue
	nil
end

#readbin(*args) ⇒ Object



184
185
186
# File 'lib/shell_helpers/pathname.rb', line 184

def readbin(*args)
	open("rb").read(*args)
end

#rel_glob(pattern, expand: false) ⇒ Object

We now have Pathname#glob



282
283
284
285
286
287
288
289
290
# File 'lib/shell_helpers/pathname.rb', line 282

def rel_glob(pattern, expand: false)
	g=[]
	self.cd { g=Dir.glob(pattern) }
	if expand
		g.map {|f| self+f} 
	else
		g.map {|f| Pathname.new(f)}
	end
end

#rel_path(base: self.class.pwd, checkdir: false) ⇒ Object



221
222
223
224
225
226
227
# File 'lib/shell_helpers/pathname.rb', line 221

def rel_path(base: self.class.pwd, checkdir: false)
	base=base.dirname unless base.directory? if checkdir
	relative_path_from(base)
rescue ArgumentError => e
	warn "#{self}.relative_path_from(#{base}): #{e}"
	self
end

#rel_path_to(target = self.class.pwd, base: self.class.pwd, mode: :rel, clean_mode: :abs_clean, inside: false, **opts) ⇒ Object

path from self to target (warning: we always assume that we are one level up self, except if inside is true) bar=SH::Pathname.new("foo/bar"); baz=SH::Pathname.new("foo/baz") bar.rel_path_to(baz) #ShellHelpers::Pathname:baz bar.rel_path_to(baz, inside: true) #ShellHelpers::Pathname:../baz note: there is no real sense to use mode: :rel here, but we don't prevent it



262
263
264
265
266
267
268
269
270
271
272
# File 'lib/shell_helpers/pathname.rb', line 262

def rel_path_to(target=self.class.pwd, base: self.class.pwd, mode: :rel, clean_mode: :abs_clean, inside: false, **opts)
	target=self.class.new(target) unless target.is_a?(self.class)
	sbase=opts[:source_base]||base
	smode=opts[:source_mode]||clean_mode
	tbase=opts[:target_base]||base
	tmode=opts[:target_mode]||clean_mode
	source=self.convert_path(base: sbase, mode: smode)
	target=target.convert_path(base: tbase, mode: tmode)
	from=inside ? source : source.dirname
	target.convert_path(base: from, mode: mode)
end


338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/shell_helpers/pathname.rb', line 338

def rm_bad_symlinks(rm:false,hidden:false)
	r=[]
	if directory?
		filter=if hidden
				->(x,_) {x.hidden?}
			else
				->(*x) {false}
			end
		find(filter:filter) do |file|
			if file.bad_symlink?
				r<<file
				file.rm if rm
			end
		end
	end
	r
end

#rm_empty_dirs(rm: true) ⇒ Object

remove all empty directories inside self this includes directories which only include empty directories



325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/shell_helpers/pathname.rb', line 325

def rm_empty_dirs(rm:true)
	r=[]
	if directory?
		find(depth:true) do |file|
			if file.directory? and file.children(false).empty?
				r<<file
				file.rmdir if rm
			end
		end
	end
	r
end

#rm_rObject

rmtree should be rm_rf, not rm_r!



27
# File 'lib/shell_helpers/pathname.rb', line 27

alias_method :rm_r, :rmtree

#rmtreeObject Also known as: rm_rf



28
29
30
31
32
# File 'lib/shell_helpers/pathname.rb', line 28

def rmtree
	require 'fileutils'
	FileUtils.rm_rf(@path)
	nil
end

#shellescapeObject



35
36
37
38
# File 'lib/shell_helpers/pathname.rb', line 35

def shellescape
	require 'shellwords'
	to_s.shellescape
end

#split_allObject

taken from facets/split_all



189
190
191
192
193
194
# File 'lib/shell_helpers/pathname.rb', line 189

def split_all
	head, tail = split
	return [tail] if head.to_s == '.' || tail.to_s == '/'
	return [head, tail] if head.to_s == '/'
	return head.split_all + [tail]
end

#sudo_mkdirObject



370
371
372
# File 'lib/shell_helpers/pathname.rb', line 370

def sudo_mkdir
	Sh.sh("mkdir -p #{shellescape}", sudo: true)
end

#sudo_mkpathObject



373
374
375
# File 'lib/shell_helpers/pathname.rb', line 373

def sudo_mkpath
	Sh.sh("mkdir -p #{shellescape}", sudo: true)
end

#text?Boolean

return true if the file is a text

Returns:

  • (Boolean)


178
179
180
181
182
# File 'lib/shell_helpers/pathname.rb', line 178

def text?
	#!! %x/file #{self.to_s}/.match(/text/)
	return false if directory?
	!binary?
end

#to_relativeObject



40
41
42
43
# File 'lib/shell_helpers/pathname.rb', line 40

def to_relative
	return self if relative?
	relative_path_from(Pathname.slash)
end