加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Bash to Python:展平目录树

发布时间:2020-12-15 21:16:19 所属栏目:安全 来源:网络整理
导读:在类Unix系统上我使用这个脚本,我希望在移植到 Python以便在Windows主机上执行时提供一些帮助: #!/bin/bashSENTINEL_FILENAME='__sentinel__'SENTINEL_MD5_CHECKSUM=''SENTINEL_SHA_CHECKSUM=''function is_directory_to_be_flattened() { local -r directo
在类Unix系统上我使用这个脚本,我希望在移植到 Python以便在Windows主机上执行时提供一些帮助:

#!/bin/bash

SENTINEL_FILENAME='__sentinel__'
SENTINEL_MD5_CHECKSUM=''
SENTINEL_SHA_CHECKSUM=''

function is_directory_to_be_flattened() {

  local -r directory_to_consider="$1"
  local -r sentinel_filepath="${directory_to_consider}/${SENTINEL_FILENAME}"

  if [ ! -f "${sentinel_filepath}" ]; then
    return 1
  fi

  if [[
      "$(
         md5 "${sentinel_filepath}" 
           | awk '{ print $NF }' 2> /dev/null
       )" 
        == "${SENTINEL_MD5_CHECKSUM}"
    && 
      "$(
         shasum -a 512 "${sentinel_filepath}" 
           | awk '{ print $1 }' 2> /dev/null
       )" 
        == "${SENTINEL_SHA_CHECKSUM}"
  ]]; then
    return 0
  else
    return 1
  fi
}

function conditionally_flatten() {

  local -r directory_to_flatten="$1"
  local -r flatten_into_directory="$2"

  if is_directory_to_be_flattened "${directory_to_flatten}"; then

    if [ ! -d "${flatten_into_directory}" ]; then
      mkdir -v "${flatten_into_directory}"
    fi

    for file_to_move in $(find ${directory_to_flatten} -type f -maxdepth 1); do
      mv 
        -v 
        -n 
        "${file_to_move}" 
        "${flatten_into_directory}"
    done
  fi
}

function flatten_directory() {

  local -r directory_to_flatten="$1"
  local -r descend_depth="$2"

  local -r flattened_directory="${directory_to_flatten}/__flattened__"

  if [ ! -d "${directory_to_flatten}" ]; then
    printf "The argument '%s' does not seem to be a directory.n" 
      "${directory_to_flatten}" 
      >&2
    return
  fi

  find "${directory_to_flatten}" 
    -type d 
    -maxdepth "${descend_depth}" 
  | 
    while read directory_path; do
      conditionally_flatten 
        "${directory_path}" 
        "${flattened_directory}"
    done
}

n_arguments="$#"

if [ "${n_arguments}" -eq 1 ]; then
  flatten_directory "$1" '1' # maybe use a constant,not a "magic #" here?
else
  echo usage: "$0" /path/to/directory/to/flatten
fi

unset is_directory_to_be_flattened
unset conditionally_flatten
unset flatten_directory

你会如何将它移植到Win Python?我是Python和Bash脚本的初学者..

如果您发现它没有任何方式,请随意升级我的实现,并提出正当理由.这不是“代码审查”,但是我在Bash上的努力“竖起大拇指/竖起大拇指”会让我感觉到我是在改进还是应该改变我完全学习的方式……

我们去了,我在Python中的尝试:(如果需要的话,批评它很难,这是我学习的唯一方法!)

#!/usr/bin/env python2.7

import sys
import os
import shutil

SENTINEL_FILENAME=''
SENTINEL_MD5_CHECKSUM=''
SENTINEL_SHA_CHECKSUM=''

DEFAULT_DEPTH = 1
FLATTED_DIRECTORY_NAME = '__flattened__'

def is_directory_to_be_flattened(directory_to_consider):
  sentinel_location = os.path.join(directory_to_consider,SENTINEL_FILENAME)
  if not os.path.isfile(sentinel_location):
    return False
  import hashlib
  with open(sentinel_location) as sentinel_file:
    file_contents = sentinel_file.read()
    return (hashlib.md5(file_contents).hexdigest() == SENTINEL_MD5_CHECKSUM
      and hashlib.sha512(file_contents).hexdigest() == SENTINEL_SHA_CHECKSUM)

def flatten(directory,depth,to_directory,do_files_here):
  if depth < 0:
    return
  contained_filenames = [f for f in os.listdir(directory)]
  if do_files_here:
    for filename in contained_filenames:
      if filename == SENTINEL_FILENAME:
        continue
      filepath = os.path.join(directory,filename)
      if not os.path.isfile(filepath):
        continue
      file_to = os.path.join(to_directory,filename)
      if not os.path.isdir(to_directory):
        os.makedirs(to_directory)
      if not os.path.isfile(file_to):
        print "Moving: '{}' -> '{}'".format(filepath,file_to)
        shutil.move(filepath,file_to)
      else:
    sys.stderr.write('Error: {} exists already.n'.format(file_to))
  next_depth = depth - 1
  for subdirectory in (d for d in contained_filenames if os.path.isdir(d)):
    if is_directory_to_be_flattened(subdirectory):
      flatten(subdirectory,next_depth,True)

def flatten_directory(to_flatten,depth):
  to_directory = os.path.join(to_flatten,FLATTED_DIRECTORY_NAME)
  if not os.path.isdir(to_flatten):
    sys.stderr.write(
      'The argument {} does not seem to be a directory.n'.format(
      to_flatten))
    return
  flatten(to_flatten,False)

def main():
  if len(sys.argv) == 2:
    flatten_directory(sys.argv[1],DEFAULT_DEPTH)
  else:
    print 'usage: {} /path/to/directory/to/flatten'.format(sys.argv[0])

if __name__ == '__main__':
  main()

虽然从代码中可以明显看出,但意图是:

>从给定目录开始
>下降到一定深度
>考虑子目录并移动其中的所有文件,当且仅当:

>该目录包含具有给定文件名的“sentinel文件”
> sentinel文件实际上是一个sentinel文件,而不仅仅是重命名为相同名称的文件

>将文件整理到搜索开始目录下的__flattened__目录中

解决方法

Python中的大多数文件处理函数都在模块“os”中 – 你会发现
os.rename(用于重命名或移动directoruy条目),os.listdir – 它为您提供目录中的文件名列表,作为第一个arg,os.walk传递 – 以递归方式遍历目录结构os.path.walk,为了做同样的事情,但是使用回调,os.path.exists,os.path.isdir,os.mkdir,是其他可能很方便的.

对于“快速而肮脏”的翻译,您也可以使用“os.system”.它允许你执行shell命令,就像它在shell中输入一样,而os.popen – 允许访问所述进程的stdin和stdout.更细致的翻译,很难,需要使用另一个模块:“subprocess”,它可以完全控制作为子进程执行的shell命令(例如,如果你需要查找,例如,它将无法在Windows上使用)

其他感兴趣的模块是sys(sys.argv是传递给脚本的参数)和shutil(包括copy,rmtree等)

你的脚本做了一些错误检查,并且它是微不足道的,考虑到“os”中的上述功能名称和基本的Python来添加它们 – 但是Python中的一个简短的“只做它”脚本可能只是:

import os,sys

dir_to_flatten = sys.argv[1]

for dirpath,dirnames,filenames in os.walk(dir_to_flatten):
    for filename in filenames:
        try:
            os.rename(os.path.join(dirpath,filename),os.path.join(dir_to_flatten,filename))
        except OSError:
            print ("Could not move %s " % os.path.join(dirpath,filename))

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读