4

Unixライクなシステムでは、このスクリプトを使用します。これは、Windowsホストで実行するためにPythonに移植する際に役立ちます。


#!/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

これをWinPythonにどのように移植しますか?私は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, to_directory, 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, depth, to_directory, 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()

コードから明らかですが、目的は次のとおりです。

  • 特定のディレクトリから開始します
  • 一定の深さまで降りる
  • 次の場合に限り、サブディレクトリを検討し、その中のすべてのファイルを移動します。
    • ディレクトリには、指定されたファイル名の「センチネルファイル」が含まれています
    • 番兵ファイルは実際には番兵ファイルであり、同じ名前に名前が変更されたファイルだけではありません
  • __flattened__検索が開始されたディレクトリの下のディレクトリにあるファイルを照合します
4

1 に答える 1

9

Pythonのほとんどのファイル処理関数は、モジュール「os」にあります。その中には、os.rename(directouruyエントリの名前変更または移動用)os.listdirがあります。これにより、ディレクトリ内のファイル名のリストが最初の引数として渡されます。 、os.walk-ディレクトリ構造os.path.walkを再帰的にウォークスルーして同じことを行いますが、コールバックを使用すると、os.path.exists、os.path.isdir、os.mkdirなどがあります。ハンディ。

「迅速で汚い」翻訳の場合は、「os.system」をcehckすることもできます。これにより、シェルに入力されたのと同じようにシェルコマンドを実行できます。os.popen-これにより、上記のプロセスのstdinおよびstdoutにアクセスできます。より注意深い翻訳は、難しいので、anotheモジュールを使用する必要があります:サブプロセスとして実行されるシェルコマンドの1つの完全な制御を与えることができる「サブプロセス」(ただし、必要な場合find、たとえば、Windowsでは使用できません)

関心のある他のモジュールはsys(sys.argvはスクリプトに渡される引数です)およびshutil(copy、rmtreeなどを含む)

スクリプトはエラーチェックを行います。上記の「os」の関数名とそれらを追加する基本的なPythonを考えると、簡単ですが、Pythonの短い「justdoit」スクリプトは次のようになります。

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))
于 2012-10-08T12:03:55.303 に答える