# File lib/automateit/shell_manager/portable.rb, line 369
  def chperm(targets, opts={})
    _replace_owner_with_user(opts)
    user = \
      if opts[:user]
        opts[:user] = opts[:user].to_s if opts[:user].is_a?(Symbol)
        if opts[:user].is_a?(String)
          begin
            Etc.getpwnam(opts[:user]).uid
          rescue ArgumentError
            :not_present
          end
        else
          opts[:user]
        end
      end

    group = \
      if opts[:group]
        opts[:group] = opts[:group].to_s if opts[:group].is_a?(Symbol)
        if opts[:group].is_a?(String)
          begin
            Etc.getgrnam(opts[:group]).gid
          rescue ArgumentError
            :not_present
          end
        else
          opts[:group]
        end
      end

    modified_entries = []
    modified_ownership = false
    modified_permission = false
    Find.find(*targets) do |path|
      modified = false
      stat = writing? || File.exists?(path) ? File.stat(path) : nil
      if opts[:mode]
        # TODO ShellManager::Portable#chperm -- process chmod symbolic strings, e.g., [ugoa...][[+-=][rwxXstugo...]...][,...]
        mode = opts[:mode] | (stat.directory? ? DIRECTORY_MASK : FILE_MASK) if stat
        unless stat and (mode ^ stat.mode).zero?
          modified = true
          modified_permission = true
          File.chmod(mode, path) if writing?
        end
      end
      if user and (not stat or user != stat.uid)
        modified = true
        modified_ownership = true
        File.chown(user, nil, path) if writing?
      end
      if group and (not stat or group != stat.gid)
        modified = true
        modified_ownership = true
        File.chown(nil, group, path) if writing?
      end
      modified_entries << path if modified
      Find.prune if not opts[:recursive] and File.directory?(path)
    end

    return false if modified_entries.empty?

    display_entries = opts[:details] ? modified_entries : targets
    display_entries = [display_entries].flatten

    if modified_permission
      msg = "chmod"
      msg << " -R" if opts[:recursive]
      msg << " 0%o" % opts[:mode] if opts[:mode]
      msg << " " << display_entries.join(' ')
      log.info(PEXEC+msg)
    end
    if modified_ownership
      msg = "chown"
      msg << " -R" if opts[:recursive]
      msg << " %s" % opts[:user] if opts[:user]
      msg << ":" if opts[:user] and opts[:group]
      msg << "%s" % opts[:group] if opts[:group]
      msg << " " << display_entries.join(' ')
      log.info(PEXEC+msg)
    end
    return targets.is_a?(String) ? modified_entries.first : modified_entries
  end