This commit is contained in:
commit
a27ddb2871
|
|
@ -0,0 +1,3 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.12" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.12" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/PBXActBackup.iml" filepath="$PROJECT_DIR$/.idea/PBXActBackup.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
import paramiko
|
||||
from scp import SCPClient
|
||||
import os
|
||||
|
||||
# === CONFIGURATION ===
|
||||
ssh_host = '192.168.130.9'
|
||||
ssh_port = 22
|
||||
ssh_user = 'root'
|
||||
ssh_password = '' # Or use SSH key (see notes below)
|
||||
remote_folder = '/temp/bc/'
|
||||
local_folder = r'C:\Backup\Telefonsentral' # Use raw string for Windows paths
|
||||
|
||||
# === SETUP LOCAL FOLDER ===
|
||||
os.makedirs(local_folder, exist_ok=True)
|
||||
|
||||
def create_ssh_client(host, port, user, password):
|
||||
client = paramiko.SSHClient()
|
||||
client.load_system_host_keys()
|
||||
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
client.connect(host, port, username=user, password=password)
|
||||
return client
|
||||
|
||||
def copy_folder(ssh_client, remote_path, local_path):
|
||||
print(f"Downloading files from {remote_path} to {local_path}...")
|
||||
|
||||
sftp = ssh_client.open_sftp()
|
||||
|
||||
# Get all remote files
|
||||
stdin, stdout, _ = ssh_client.exec_command(f"find {remote_path} -type f")
|
||||
remote_files = [line.strip() for line in stdout.readlines()]
|
||||
|
||||
for remote_file in remote_files:
|
||||
relative_path = os.path.relpath(remote_file, remote_path).replace('/', os.sep)
|
||||
local_file_path = os.path.join(local_path, relative_path)
|
||||
|
||||
local_dir = os.path.dirname(local_file_path)
|
||||
os.makedirs(local_dir, exist_ok=True)
|
||||
|
||||
try:
|
||||
print(f"Downloading {remote_file} → {local_file_path}")
|
||||
sftp.get(remote_file, local_file_path)
|
||||
except Exception as e:
|
||||
print(f"Failed to download {remote_file}: {e}")
|
||||
|
||||
sftp.close()
|
||||
|
||||
def list_remote_files(ssh, path):
|
||||
# Returns list of full file paths (e.g. /home/user/data/file.txt)
|
||||
stdin, stdout, stderr = ssh.exec_command(f"find {path} -type f")
|
||||
files = [line.strip() for line in stdout.readlines()]
|
||||
return files
|
||||
|
||||
def list_local_files(path):
|
||||
# Returns full local file paths
|
||||
local_files = []
|
||||
for dirpath, _, filenames in os.walk(path):
|
||||
for f in filenames:
|
||||
full_path = os.path.normpath(os.path.join(dirpath, f))
|
||||
local_files.append(full_path)
|
||||
return local_files
|
||||
|
||||
def sync_delete_unmatched(remote_files, local_base_path, remote_base_path):
|
||||
print("Checking for stale local files to delete...")
|
||||
|
||||
# Compute relative paths from remote files
|
||||
remote_relative = [
|
||||
os.path.normpath(f.replace(remote_base_path, '').lstrip('/').replace('/', os.sep))
|
||||
for f in remote_files
|
||||
]
|
||||
expected_local = {os.path.normpath(os.path.join(local_base_path, rel)) for rel in remote_relative}
|
||||
|
||||
local_files = set(list_local_files(local_base_path))
|
||||
|
||||
to_delete = local_files - expected_local
|
||||
for f in to_delete:
|
||||
try:
|
||||
print(f"Deleting stale file: {f}")
|
||||
os.remove(f)
|
||||
except Exception as e:
|
||||
print(f"Failed to delete {f}: {e}")
|
||||
|
||||
def main():
|
||||
try:
|
||||
ssh = create_ssh_client(ssh_host, ssh_port, ssh_user, ssh_password)
|
||||
|
||||
# 1. List remote files
|
||||
remote_files = list_remote_files(ssh, remote_folder)
|
||||
|
||||
# 2. Download all files from remote
|
||||
copy_folder(ssh, remote_folder, local_folder)
|
||||
|
||||
# 3. Delete local files not on remote
|
||||
sync_delete_unmatched(remote_files, local_folder, remote_folder)
|
||||
|
||||
ssh.close()
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in New Issue