sshj icon indicating copy to clipboard operation
sshj copied to clipboard

How can I get the size of a directory in bytes with SFTP/SCP

Open insinfo opened this issue 2 years ago • 3 comments

How can I get the size of a directory in bytes with SFTP/SCP to calculate copy progress

insinfo avatar Apr 19 '22 22:04 insinfo

Out of curiosity: what do you mean with "size of a directory" - the recursive amount of files/links inside this directory?

tmssngr avatar May 16 '22 09:05 tmssngr

@tmssngr How can I know the size of a directory in bytes before downloading it, so I can calculate the progress ? I implemented code for this in dart a while ago for SCP, but I believe sshj should have this right?

 ///return total size in bytes of Directory
  int getSizeOfDirectory(
      Pointer<ssh_session_struct> session, String remoteDirectoryPath,
      {bool isThrowException = true}) {

    var cmdToGetTotaSize =
        "find $remoteDirectoryPath -type f -print0 | xargs -0 stat --format=%s | awk '{s+=\$1} END {print s}'";
    String? cmdRes;
    try {
      cmdRes = execCommandSync(session, cmdToGetTotaSize);
      if (cmdRes.trim().isEmpty) {
        //check is symbolic link    
        cmdRes = execCommandSync(session, 'file $remoteDirectoryPath');
     //is it a symbolic link?
        if (cmdRes.contains('symbolic')) {
        // get the real path of the symbolic link
          var cmdRe =
              execCommandSync(session, 'readlink -f $remoteDirectoryPath');
          if (cmdRe.trim().isNotEmpty) {
            cmdRes = execCommandSync(session,
                "find ${cmdRe.replaceAll(RegExp(r'\n'), '')} -type f -print0 | xargs -0 stat --format=%s | awk '{s+=\$1} END {print s}'");
          }
        }
      }
      //for old debian like debian  6
      //old debian bug 1.57903e+10
      if (cmdRes.contains('e+')) {
        cmdRes = execCommandSync(session,
            'find $remoteDirectoryPath -type f -print0 | xargs -0 stat --format=%s |  paste -sd+ - | bc -l');
      } else if (int.tryParse(cmdRes) == null) {
     
        cmdRes = execCommandSync(session,
            'find $remoteDirectoryPath -type f -print0 | du -scb -L --apparent-size --files0-from=- | tail -n 1');
        return int.parse(cmdRes.split(' ').first.trim());
      }

      return int.parse(cmdRes);
    } catch (e) {
      print(
          'getSizeOfDirectory: $e \r\n cmdToGetTotaSize: $cmdToGetTotaSize \r\n cmdRes: $cmdRes');
      if (isThrowException) {
        throw LibsshGetFileSizeException(
            'Unable to get the size of a directory in bytes, \r\n cmd: $cmdToGetTotaSize cmdResult: $cmdRes');
      }
    }
    return 0;
  }

code from libssh_binding

insinfo avatar May 16 '22 19:05 insinfo

Why do you think sshj would need to have this? As you can see from libssh, this is not part of the SSH protocol itself, but rather an intricate amount of calls and commands executed on the remote machine.

hierynomus avatar Aug 08 '22 12:08 hierynomus