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